Unome
Unome

Reputation: 6900

Multipart-form data POST to upload image not working after boundary is added in Swift

So I'm trying to do a multi-part post request in Swift using the following format:

user_id 3232424234
photo *PHOTO DATA*

I set up my request as shown at the bottom of this post and am getting the following error:

Optional(Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x7f86235cfe40 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=ENDPOINTURL, NSErrorFailingURLKey=ENDPOINTURL, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.})

This error seems extremely odd to me because I can make it go away by omitting the boundary requirements for the POST request, but the server than explodes with a 500 and lets the client know it omitted the boundary reqs, so yah. I am probably doing something wrong in Swift. Below is my code to make the request. Let me know if more info is needed, thx guru's of the world.

//Inputs in this scope are an "id" and a "photo"
let url = NSURL(string: "**URL**")
let boundary = NSUUID()
let request = NSMutableURLRequest(URL: url!)

request.HTTPMethod = "POST"
request.setValue("multipart/form-data; boundary=--\(boundary)", forHTTPHeaderField: "Content-Type")

let parameterBody:NSDictionary = [
    "user_id": id,
]

let data:NSMutableData = NSMutableData()

parameterBody.enumerateKeysAndObjectsUsingBlock { (parameterKey: AnyObject, parameterValue: AnyObject, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
    data.appendData(NSString(string: "--\(boundary)\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
    data.appendData(NSString(string: "\(parameterKey) \(parameterValue)\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
}

data.appendData(NSString(string: "--\(boundary)\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
data.appendData(NSString(string: "photo").dataUsingEncoding(NSUTF8StringEncoding)!)
data.appendData(photo.imageData as! NSData)
data.appendData(NSString(string: "--\(boundary)--\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)

request.setValue("\(data.length)", forHTTPHeaderField: "Content-Length")

let task = NSURLSession.sharedSession().uploadTaskWithRequest(request, fromData: data) { (responseJSON: AnyObject?, response: NSURLResponse?, error: NSError?) -> Void in
    //Here I handle the response and check for errors.
}

task.resume()

Upvotes: 1

Views: 4539

Answers (1)

Rob
Rob

Reputation: 438467

There are a ton of issues here:

  1. The boundary should be NSUUID().UUIDString.

  2. When you add the boundary to the Content-Type header, you should not add -- there.

  3. The individual parts of the multipart request are not well-formed. For example, you're missing the Content-Disposition.

  4. It's not critical, but you do not need to set Content-Length of the request. That's done for you.

I'd suggest you refer to this answer which provides example of how to form multipart request: Upload image with parameters in Swift. Or consider using Alamofire, which takes care of all of this for you.

Upvotes: 1

Related Questions