简体   繁体   English

无法使用Alamofire通过服务器上传音频文件

[英]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. 这里的重点是将音频录制为.wav,在应用程序中以及在continueRegist部分中播放,我想使用alamofire调用put方法并将音频上传到我们的amazons3server。 Recording and playing audio part is totally working. 录制和播放音频部分完全可以正常工作。 The problem is in the method continueRegist. 问题出在方法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. 然后,我从s3服务器的url检查它。 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. 另外,当我尝试从Postman上传并选择文件并提供正确的表单数据信息时,我可以收听上传到s3服务器的声音。 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. 截屏时忘了选择文件,但它只是一个.wav文件。

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. 问题出在您的Alamofire请求中:您正在使用JSON中的音频数据构建JSON。 However, you can check in Postman the HTTP code(top right/under send) that the request is Multi Part Form Data. 但是,您可以在邮递员中检查HTTP代码(右上方/发送下方),该请求是“多部分表单数据”。

How to implement a multipart Alamofire: It should be something similar to that I am not sure about appendBodyPart statements. 如何实现多部分Alamofire:它应该类似于我不确定appendBodyPart语句的内容。 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. 在Alamofire.upload语句中,确保将withName设置为您的上传API参数名称。 I used voice , you might have different parameter name. 我使用voice ,您可能具有不同的参数名称。
  4. upload.uploadProgress() is optional. upload.uploadProgress()是可选的。 You can delete it if you don't need it. 如果不需要,可以将其删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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