Отправка звука из Swift App на PHP Server, и где-то звук теряется

Я делаю приложение в Swift, которое записывает некоторый звук, а затем отправляет эту запись на мой PHP-сервер.

Приложение записывает аудио клип в порядке (его можно воспроизводить без проблем). Когда я println записанный аудиоклип, он показывает нагрузки и нагрузки байтовых данных (то же самое, когда я помещаю звук в обертку NSData ). Все это говорит мне, что звук в приложении хорош.

Файл PHP, захватывающий запись на моем сервере, также отлично работает и без ошибок.

Но где-то вдоль линии записанный аудиоклип теряется.

Быстрый код, который загружает запись:

 // 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-код в файле 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 :

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

Так что catch.php ничего не получает.

Я отправляю запись неправильно, или я неправильно поймаю запись? Или оба?

Заранее спасибо.

Solutions Collecting From Web of "Отправка звука из Swift App на PHP Server, и где-то звук теряется"

Ваш PHP-код в основном прекрасен. Часть $_FILES в порядке, но php://input недоступен с enctype="multipart/form-data" .

Проблема заключается в том, как вы генерируете HTTP-запрос в вашем Swift-коде. Главным образом заголовки HTTP. При создании заголовков для многочастных данных шаблон таков (если мы выбрали AAAAA нашей границей):

  • Наша выбранная граница: «AAAAA»
  • Тип контента = "multipart / form-data; border = 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 

Если вы снова столкнетесь с такими вещами, при отладке сетевого кода, подобного этому, мне нравится использовать инструменты, которые позволяют мне проверять передаваемые данные HTTP-сети. Мне лично нравится HTTPScoop, потому что он прост, но вы также можете использовать BurpSuite или Charles

Я просто проверил ваш код и сравнил HTTP-трафик с тем, что произошло, когда я сделал запрос с завитком

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