将音频从Swift App发送到PHP Server,某些地方音频丢失 [英] Sending audio from a Swift App to PHP Server, and somewhere the audio is lost
问题描述
我正在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屋!