Sending sound from Swift App to PHP Server and somewhere the sound is lost

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

The application records the audio clip in order (it can be played without any problems). When I println

recorded the audio clip it shows loads and loads of byte data (same thing when I put the sound in a wrapper NSData

). This all tells me that the sound in the app is good.

The PHP file grabbing the entry on my server works fine too and no errors.

But somewhere along the line, the recorded audio clip is lost.

Quick code that loads the entry:

// 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 in the file catch.php

that should receive the entry:

$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";

      

And whenever I run the whole thing, I get the following output from catch.php

:

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

      

So it catch.php

gets nothing.

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

Thanks in advance.

+3


source to share


2 answers


Your PHP code is mostly fine. Part $_FILES

ok but not available c . php://input

enctype="multipart/form-data"

The problem is how you generate the HTTP request in your Swift code. Mostly HTTP headers. When creating headers for multipart data, the template is as follows (assuming we chose AAAAA as our boundary):

  • Our chosen border: "AAAAA"
  • Content type = "multipart / form-data; border = AAAAA"
  • Start Bounary = --AAAAA
  • End Boundary = --AAAAA -

So, correcting the code a 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

      

If you run into this sort of thing again while debugging networking code like this, I like to use tools that allow me to inspect the HTTP data being sent. I personally like HTTPScoop because it is simple, but you can also use BurpSuite or Charles

I just skipped your code and compared the HTTP traffic to what happened when I made the request with curl

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

      

+3


source


Can you tell me what is the use of border and contentType? Many thanks. Does the border always remain the same for every action submitting to the server? I hope someone can clarify and explain this to me. Many thanks.



0


source







All Articles