从Swift应用程序发送audio到PHP服务器,以及audio丢失的地方
我正在Swift中制作一个应用程序,用于录制一些audio,然后将该录制内容发送到我的PHP服务器。
该应用程序loggingaudio剪辑罚款(可以播放没有问题)。 当我println
录制的audio剪辑时,它显示了加载和加载的字节数据(当我把audio放入一个NSData
包装器时)。 这一切都表明,我的应用程序内的audio是好的。
捕捉我的服务器上的logging的PHP文件也工作正常,没有错误。
但是沿线的某处录制的audio剪辑会丢失。
上传logging的Swift代码:
// 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()
应该接收logging的文件catch.php
中的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
获得以下输出:
Caught the following: Contents:'' Files:array ( )
所以catch.php
没有收到任何东西。
我发送的录音是否错误,或者录制错误? 或两者?
提前致谢。
你的PHP代码大多是好的。 $_FILES
部分是可以的,但是php://input
不可用于enctype="multipart/form-data"
。
问题在于如何在Swift代码中生成HTTP请求。 主要是HTTP头。 为多部分数据创build标题时,模式是这样的(如果我们selectAAAAA作为我们的边界):
- 我们select的边界:“AAAAA”
- Content Type =“multipart / form-data; boundary = AAAAA”
- 开始Bounary = –AAAAA
- 结束边界= –AAAAA–
所以通过修改你的代码一点:
// 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
如果再次遇到这样的情况,在debugging这样的networking代码时,我喜欢使用工具来检查正在传输的HTTPnetworking数据。 我个人喜欢HTTPScoop,因为它很简单,但是你也可以使用BurpSuite或Charles
我只是运行你的代码,并比较HTTPstream量和我用curl发出请求时发生的事情
curl -X POST http://localhost/\~cjwirth/catch.php -F "file=@Untitled.m4a"