1

I am trying to upload an image to a backend client using swift. Trouble is I can't seem to get the formatting correct for the httpbody. I do not want to use a multipart form for uploading as I don't know how to handle that on the backend.

Here is the code I have.. it doesn't work when I view the image online it doesn't display and it is only like 70kb which I know is definitely not how big the image is.

var bodyString: String = "session_id=\(session_id)&location_id=\(location_id)"
bodyString = bodyString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
var body = NSMutableData.alloc()
body.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
if image != nil{
    var imageData = UIImageJPEGRepresentation(image,0.5)
    body = NSMutableData.alloc()
    //var imageDataString = imageData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
    bodyString = "session_id=\(session_id)&location_id=\(location_id)&image_data="
    bodyString = bodyString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
    body.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
    var imageString = "&image_data=\(imageData)"
    body.appendData(imageData)
    }
req.HTTPBody = body

UPDATE: so I decided to go the base64 route but it still doesn't seem to be working I think because I am encoding it as an ntf8string is this the correct way to be doing this?

var imageData = UIImageJPEGRepresentation(image,0.5)
var imageDataString = imageData.base64EncodedStringWithOptions(.allZeros)
body = NSMutableData.alloc()
bodyString = "session_id=\(session_id)&location_id=\(location_id)&tag_type=\(tag_type)&image_data=\(imageDataString)"
bodyString = bodyString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
body.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)

and on the backend I am decoding it like:

image_data_decoded = base64.b64decode(image_data)
Tyler
  • 2,346
  • 6
  • 33
  • 59
  • OK, this is better. A couple of things: First, do not use `NSMutableData.alloc()`. It's just `NSMutableData()`. 2. You should look at `bodyString` and make sure it looks OK (i.e. that none of those variables were optionals which ended up inserting a `Optional(...)` into your string. 3. You might want to use something like [Charles](http://charlesproxy.com) to look at the actual request and make sure it's ok. You haven't shared the full configuration of the `NSMutableURLRequest`, so we simply cannot comment on that. – Rob May 03 '15 at 16:02
  • On the server side, is that PHP? I'm not familiar with `base64.b64decode`. In PHP, I would be inclined to use [`base64_decode`](http://php.net/manual/en/function.base64-decode.php). Regardless, you probably want to examine `image_data` and make sure it got there unmolested and then confirm what precisely `image_data_decoded` produced. – Rob May 03 '15 at 16:11

1 Answers1

0

You cannot post binary data in a application/x-www-form-urlencoded request like this. Actually, the code in your question looks like it will try to send a hexadecimal string representation of the binary data, which, probably is not what you intended and even if you did intend to do that, (a) you would have to decode it somehow on the server side; (b) note that this is very inefficient (more than doubles the size of the image payload): and (c) would need to be percent escaped in the request. But I don't think you intended that at all, anyway, so that is probably all moot.

One would generally either create multipart/form-data request as outlined here (in which the uploaded file comes in as a file, e.g. $_FILES in PHP), or one would convert this binary data to text (e.g. using base64) and the the server code has convert the base64 value for image_data key back to binary data.

By the way, I might suggest Alamofire or AFNetworking as alternatives to trying to create requests properly. It doesn't change the underlying issue (you have to pick between a base64 encoding or multipart requests), but it simplifies the Swift code.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks for this... still can't seem to get it working using the base64 encoding. I updated my question with the current code. Also would doing it as multipart/form-data make it quicker to upload? and would I be able to upload a video with the base64 way (no longer than 10s) or would I need to use the multipart form for videos? – Tyler May 03 '15 at 15:42
  • Re `multipart/form-data` be quicker? I suspect so, because your hexadecimal string technique would have made it 100% larger, and even base64 makes is 33% larger. By using `multipart/form-data`, the payload is not enlarged in order to convert it to a text-friendly format (plus the server code is simpler and more robust when handling large uploads). – Rob May 03 '15 at 16:10
  • ok got it working with multipart.. so much easier once I was on the right track so thank you! – Tyler May 03 '15 at 18:13