将音频从Swift App发送到PHP Server,某些地方音频丢失 [英] Sending audio from a Swift App to PHP Server, and somewhere the audio is lost

查看:115
本文介绍了将音频从Swift App发送到PHP Server,某些地方音频丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Swift中创建一个记录一些音频的应用程序,然后将该记录发送到我的PHP服务器。

I am making an App in Swift that records some audio and then sends that recording to my PHP server.

应用程序记录音频剪辑正常(可以是回放没有问题)。当我 println 录制的音频片段时,它会显示字节数据的加载和加载(当我将音频放入 NSData 包装)。这一切都告诉我,应用程序中的音频很好。

The App records the audio clip fine (it can be played back with no problem). When I println the recorded audio clip it shows loads and loads of byte data (same when I put the audio into an NSData wrapper). This all suggests to me that the audio is fine inside the app.

在我的服务器上捕获录音的PHP文件也可以正常运行而且没有错误。

The PHP file catching the recording on my server also works fine and without errors.

但在某个地方,录制的音频片段会丢失。

But somewhere along the line the recorded audio clip gets lost.

上传录音的Swift代码:

Swift code that uploads the recording:

// The variable "recordedFileURL" is defined earlier in the code like this:

currentFilename = "xxxx.m4a"
let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsDir: AnyObject=dirPaths[0]
recordedFilePath = docsDir.stringByAppendingPathComponent(self.currentFilename)
recordedFileURL = NSURL(fileURLWithPath: self.recordedFilePath)

// "currentFilename", "recordedFilePath" and "recordedFileURL" are all global variables

// This recording stored at "recordedFileURL" can be played back fine.

let sendToPath = "http://......../catch.php"
let sendToURL = NSURL(string: sendToPath)
let recording: NSData? = NSData(contentsOfURL: recordedFileURL)
let boundary = "--------14737809831466499882746641449----"
let contentType = "multipart/form-data;boundary=\(boundary)"

var request = NSMutableURLRequest()
request.URL = sendToURL
request.HTTPMethod = "POST"
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue(recId, forHTTPHeaderField: "REC-ID") // recId is defined elsewhere

var body = NSMutableData()
var header = "Content-Disposition: form-data; name=\"\(currentFilename)\"; filename=\"\(recordedFilePath)\"\r\n"

body.appendData(("\r\n-\(boundary)\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData((header as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(("Content-Type: application/octet-stream\r\n\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)

body.appendData(recording!) // adding the recording here

body.appendData(("\r\n-\(boundary)\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)

request.HTTPBody = body

var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in

    println("upload complete")
    let dataStr = NSString(data: data, encoding: NSUTF8StringEncoding)
    println(dataStr)

})

task.resume()

文件中的PHP代码<应该接收录音的code> catch.php

$contents = file_get_contents('php://input');
$files = $_FILES;

echo "Caught the following:/r/n";
echo "Contents:" . var_export($contents) . "/r/n";
echo "Files:" . var_export($files) . "/r/n";

每当我运行所有这些时,我从 catch获得以下输出。 php

And whenever I run all of this I get the following output from catch.php:

Caught the following:
Contents:''
Files:array (
)

所以 catch.php 根本没有收到任何东西。

So catch.php isn't receiving anything at all.

我发错了录音,还是录音错了?或两者兼而有之?

Am I sending the recording wrong, or am catching the recording wrong? Or both?

提前致谢。

推荐答案

您的PHP代码大多数都很好。 $ _ FILES 部分没问题,但 php:// input 不适用于 enctype =multipart / form-data

Your PHP code is mostly fine. The $_FILES part is OK, but php://input is not available with enctype="multipart/form-data".

问题在于如何在Swift代码中生成HTTP请求。主要是HTTP标头。
为多部分数据创建标题时,模式是这样的(如果我们选择AAAAA作为我们的边界):

The problem is with how you are generating the HTTP request in your Swift code. Mainly the HTTP headers. When creating the headers for multipart data, the pattern is this (if we choose AAAAA to be our boundary):


  • 我们的选择边界:AAAAA

  • 内容类型=multipart / form-data; boundary = AAAAA

  • Beginning Bounary = --AAAAA

  • 结束边界= --AAAAA -

  • Our chosen boundary: "AAAAA"
  • Content Type = "multipart/form-data;boundary=AAAAA"
  • Beginning Bounary = --AAAAA
  • Ending Boundary = --AAAAA--

所以通过稍微修改你的代码:

So by fixing up your code a little bit:

// This was your main problem
let boundary = "--------14737809831466499882746641449----"
let beginningBoundary = "--\(boundary)"
let endingBoundary = "--\(boundary)--"
let contentType = "multipart/form-data;boundary=\(boundary)"

// recordedFilePath is Optional, so the resulting string will end up being 'Optional("/path/to/file/filename.m4a")', which is wrong.
// We could just use currentFilename if we wanted
let filename = recordedFilePath ?? currentFilename
var header = "Content-Disposition: form-data; name=\"\(currentFilename)\"; filename=\"\(recordedFilePath!)\"\r\n"

var body = NSMutableData()
body.appendData(("\(beginningBoundary)\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData((header as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(("Content-Type: application/octet-stream\r\n\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(recording!) // adding the recording here
body.appendData(("\r\n\(endingBoundary)\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)

var request = NSMutableURLRequest()
request.URL = sendToURL
request.HTTPMethod = "POST"
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue(recId, forHTTPHeaderField: "REC-ID") // recId is defined elsewhere
request.HTTPBody = body

如果遇到这样的事情再次,在调试这样的网络代码时,我喜欢使用工具让我检查正在传输的HTTP网络数据。我个人喜欢 HTTPScoop ,因为它很简单,但你也可以使用 BurpSuite Charles

In case you run into things like this again, when debugging networking code like this, I like to use tools that let me inspect the HTTP Network data being transferred. I personally like HTTPScoop because its simple, but you can also use BurpSuite or Charles

我刚刚运行了你的代码,并将HTTP流量与我用curl发出请求时的情况进行了比较

I just ran your code through, and compared the HTTP traffic with what happened when I made the request with curl

curl -X POST http://localhost/\~cjwirth/catch.php -F "file=@Untitled.m4a"

这篇关于将音频从Swift App发送到PHP Server,某些地方音频丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆