3

I'm sending a base64 encoded image to a server as part of a post request using NSMutableURLRequest. What I log as the post body and what the server receives are not the same thing. The server seems to get a truncated version, as though the connection aborts midway. See the code below:

NSString *dataStr = [NSString stringWithFormat:@"request_data=%@",reqStr];
NSLog(@"datastr is %@",dataStr);
NSData *dataForUrl = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"nsdata length is: %i",[dataForUrl length]);
[urlRequest setHTTPBody:dataForUrl];
[urlRequest setValue:[NSString stringWithFormat:@"%d", [dataForUrl length]] forHTTPHeaderField:@"Content-Length"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *res, NSData *data, NSError *err) {
    // ... 
}

The first log statement shows the correct data. I even took the base64 part of the string to http://www.motobit.com/util/base64-decoder-encoder.asp, decoded it as a jpg, and it is the correct image. The second log statement shows that the length is the right size (422624 when the picture was 422480, for example).

I can't find anything wrong with the connection details or the data. The phone makes the connection, sends some data, then either the phone stops sending or the server stops receiving. What could cause that?

Edit: link to sample data http://pastebin.com/BS9HjKhg

Edit2: The server or iOS is converting the +'s from the image to spaces. I'll post an answer when I figure out the right way to send it.

brodney
  • 1,176
  • 2
  • 14
  • 29
  • does your client-side connection ends with some error or success? – sergio Jan 14 '13 at 17:47
  • I actually get a successful response back from the server, meaning it got data and at least some of the data was there. Since the image data is at the end of the string, it gets truncated, and the server gives various errors depending on the size of the base64 string received. – brodney Jan 14 '13 at 17:52
  • 1
    I suspect this has to do with the server... does the server log reveal anything? – sergio Jan 14 '13 at 17:57
  • It does show some information, though entries longer than 255 characters are truncated. Typically the error is invalid length of a base64 string, assuming more than 201 characters were transferred for it. Otherwise, it just accepts the data and shows the image error later in the dashboard. Do I need to be using any http headers ? – brodney Jan 14 '13 at 18:07

2 Answers2

4

I was able to compare a full sample from the server vs what xcode logged, and found the + converted to [space]. Since that was the only character having a problem and url encoding is buggy in iOS, I just did

NSString *dataStr = [NSString stringWithFormat:@"request_data=%@",[reqStr stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"]];

The server is accepting them again. I'm still not sure whether the server was the problem or it was iOS. The other OS's that connect use the same application/x-www-form-urlencoded as their content type with no problems.

brodney
  • 1,176
  • 2
  • 14
  • 29
1

I would suggest doing the conversion from Base64 string into NSData through Nick Lockwood's Base64 class.

That

NSData *dataForUrl = [dataStr dataUsingEncoding:NSUTF8StringEncoding];

worries me a bit (even more after looking at how Base64 is implements the conversion)...

sergio
  • 68,819
  • 11
  • 102
  • 123
  • I just tried writing to a file and using NSInputStream, and tried using [NSURLConnection sendSynchronousRequest:] with the same results. – brodney Jan 14 '13 at 18:41
  • what do you mean by "the same result"? have you tried out Base64 and it produces the same output as `dataUsingEncoding:`? – sergio Jan 14 '13 at 18:45
  • 1
    the fact is, I really don´t know what is happening. I thought that maybe using `dataUsingEncoding:` to convert your `NSString` (a part of which is Base64 data) into `NSData` was not the correct way. Possibly the problem is in the string you are sending, maybe you can try and post a part of it... – sergio Jan 14 '13 at 19:14
  • Added link to sample data in my question. There's nothing sensitive in there so it has not been modified. You can convert the base64 part to a jpg to see the original image. – brodney Jan 14 '13 at 19:22
  • how does the server know where the image data begin? shouldn´t you be also url-encoding the non-base64 part of your string? – sergio Jan 14 '13 at 19:28
  • The tilde is a separator, so it reads roughly "Element with id 524 with value /9j/4A...". The server architect was unfamiliar with JSON it seems. The server expects the data as is, but I will try encoding to see what happens. – brodney Jan 14 '13 at 19:34