从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"