简体   繁体   中英

Can't upload audio file through server using Alamofire

class VoiceRecogViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {


var audioPlayer: AVAudioPlayer?
var audioRecorder: AVAudioRecorder?
var error: NSError?
var soundFileURL: URL?
var soundFilePath: String = ""
var data : NSData?

@IBOutlet weak var startRocordButton: UIButton!
@IBOutlet weak var stopRecordButton: UIButton!
@IBOutlet weak var playRecordButton: UIButton!
@IBOutlet weak var continueButton: UIButton!

override func viewDidLoad() {

    super.viewDidLoad()
    playRecordButton.isEnabled = false
    stopRecordButton.isEnabled = false

    let dirPaths =
        NSSearchPathForDirectoriesInDomains(.documentDirectory,
                                            .userDomainMask, true)

    let docsDir = dirPaths[0]
    soundFilePath = (docsDir as NSString).appendingPathComponent("sound.wav")
    soundFileURL = URL(fileURLWithPath: soundFilePath)

    let recordSettings = [AVEncoderAudioQualityKey: AVAudioQuality.min.rawValue,
                          AVEncoderBitRateKey: 16,
                          AVNumberOfChannelsKey: 2,
                          AVSampleRateKey: 44100.0] as [String : Any]

    let audioSession = AVAudioSession.sharedInstance()
    try! audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: [])
    try! audioSession.setActive(true)

    if let err = error {
        print("audioSession error: \(err.localizedDescription)")
    }

    do {
        audioRecorder = try AVAudioRecorder(url: soundFileURL!,
                                            settings: recordSettings as [String : AnyObject])
    } catch {
        audioRecorder = nil
    }

    audioRecorder?.prepareToRecord()

    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


@IBAction func startRecord(_ sender: AnyObject) {
    if audioRecorder?.isRecording == false {
        playRecordButton.isEnabled = false
        startRocordButton.isEnabled = false
        stopRecordButton.isEnabled = true
        audioRecorder?.record()
    }
}

@IBAction func stopRecord(_ sender: AnyObject) {
    stopRecordButton.isEnabled = false
    playRecordButton.isEnabled = true
    startRocordButton.isEnabled = true

    if audioRecorder?.isRecording == true {
        audioRecorder?.stop()
    } else {
        audioPlayer?.stop()
    }
}

@IBAction func playRecord(_ sender: AnyObject) {
    if audioRecorder?.isRecording == false {
        stopRecordButton.isEnabled = true
        startRocordButton.isEnabled = false
    }

    do {
        try audioPlayer = AVAudioPlayer(contentsOf: soundFileURL!)
        audioPlayer?.delegate = self
        audioPlayer?.prepareToPlay()
        audioPlayer?.play()
    } catch {
        print("audioPlayer error")
    }
}

@IBAction func continueRegist(_ sender: AnyObject) {

    let headers: HTTPHeaders = ["Authorization": "Token ___(**token**)_____",
                                "Accept": "application/json"]

    data = NSData (contentsOf: soundFileURL!)

    let parameters: Parameters = ["from_account_id": "3",
                                  "to_account_id": "4",
                                  "file": data!,
                                 ]

    let URL = "http://leaofımjpüsmfweüdıpckfw"

            Alamofire.request(URL, method: .put, parameters: parameters, headers: headers).responseJSON { response in
                if let data = response.result.value {
                    print(data)
                }
            }
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    startRocordButton.isEnabled = true
    stopRecordButton.isEnabled = false
}

func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
    print("Audio Play Decode Error")
}

func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
}

func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
    print("Audio Record Encode Error")
}

I shared my code above. Here the point is recording audio as .wav, playing it in app and in continueRegist part I want to call put method with alamofire and upload the audio to our amazons3server. Recording and playing audio part is totally working. The problem is in the method continueRegist. After calling the method, I am getting the correct response, it looks successful. Then, I am checking it from the url of our s3 server. The audio seems like uploaded but when I download and play it, it is not working. I could not figure out the where problem is.

Also, when I try to upload from Postman with selecting file and giving the right form data information, I can listen the sound I uploaded to the s3 server. What might be wrong here?

Below you can find my request through Postman:

Body: 身体

I forgot to choose the file when I am taking the screenshot but it is simply a .wav file.

Headers 头

Please do not hesitate to ask me questions those does not satisfy you.

Hope you can help me.

Thanks!

The problem is in your Alamofire Request: You are building a JSON with the audio data in the JSON. However, you can check in Postman the HTTP code(top right/under send) that the request is Multi Part Form Data.

How to implement a multipart Alamofire: It should be something similar to that I am not sure about appendBodyPart statements. They depend on your case

let audioData: NSData = ...//should be loaded from the file

Alamofire.Manager.upload(.PUT,
                          URL,
                          headers: headers,
                          multipartFormData: { multipartFormData in
                            multipartFormData.appendBodyPart(data: "3".dataUsingEncoding(NSUTF8StringEncoding), name: "from_account_id")
                            multipartFormData.appendBodyPart(data: "4".dataUsingEncoding(NSUTF8StringEncoding), name: "to_account_id")
                            multipartFormData.appendBodyPart(data: audioData, name: "file", fileName: "file", mimeType: "application/octet-stream")
                            },
                          encodingCompletion: { encodingResult in
                            switch encodingResult {

                            case .Success(let upload, _, _):
                                upload.responseJSON { response in

                                }

                            case .Failure(let encodingError):
                                // Error while encoding request:
                            }
})

Following is the code to upload audio file:

let uploadAudioURL = "http://<your post API url>"



    let header : [String:String] = [
        "Authorization" : "<your authorisation token>"
    ]

    let voiceData = try? Data(contentsOf: <url of audio file to upload>)


    let params : [String:String] = [
        "length" : "39000",
        "title" : "Trying to upload",
    ]

    Alamofire.upload(
        multipartFormData: { (multipartFormData) in
            multipartFormData.append(voiceData!, withName: "voice", fileName: "TempRecordedAudioFile", mimeType: "audio/m4a")
            for (key, value) in params {
                multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
            }
    },
        usingThreshold : SessionManager.multipartFormDataEncodingMemoryThreshold,
        to : uploadAudioURL,
        method: .post,
        headers: header){ (result) in

            switch result {
            case .success(let upload, _, _):

                upload.uploadProgress(closure: { (Progress) in
                    print("Upload Progress: \(Progress.fractionCompleted)")
                })

                upload.responseJSON { response in

                    if let JSON = response.result.value {
                        print("Response : ",JSON)

                    }
                }

            case .failure(let encodingError):
                print(encodingError)
            }

    }

Hopefully it will help.

Some points to note for using the above code snippet:

  1. Ensure you provide your upload URL
  2. Add needed authorisation header details.
  3. In the Alamofire.upload statement ensure the withName is set to your upload API parameter name. I used voice , you might have different parameter name.
  4. upload.uploadProgress() is optional. You can delete it if you don't need it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM