HTTPS POST from iPhone using NSURLConnection hangs

2019-04-29 13:01发布

问题:

I'm using NSURLConnection to make an async HTTPS POST to our webservice to upload a jpg. It works fine most of the time.

But when the post body is between 196609 and 196868 bytes (inclusive), the connection hangs after the file has been uploaded 100% (didSendBodyData tells me that it's 100% sent). Then after 5 minutes, the connection times out with the message "The network connection was lost." Larger and smaller filesizes work. I've tested this by capping the filesize of the file that I add to the post body.

The content length is getting set correctly. See the code below.

The upload looks fine when I upload to netcat via HTTP. The entire body of the message gets through. But I suspect something's going wrong because of the SSL encryption, like it's buffering an SSL encrypted block frame.

Is there a bug in the iPhone's SSL code that makes it not upload the entire post body even though it's reporting that it is, or something else?

Here's the section where I set the content length and append the file to the multi-part POST body. You can see i'm capping the filesize manually, to test.

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsurl];
[request setHTTPMethod:@"POST"];
[request setTimeoutInterval:1];
[request addValue:@"close" forHTTPHeaderField: @"Connection"];

// Add headers and POST information
NSLog( @"Posting file." );
NSString *stringBoundary = [NSString stringWithString:@"0xKhTmLbOuNdArY"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",stringBoundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
NSMutableData *postBody = [NSMutableData data];

...

[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"uploadFile\"; filename=\"upload.jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Type: image/jpg\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
NSLog( @"file size...%d", [uploadFile length] );
//[postBody appendData:uploadFile];
[postBody appendData:[NSData dataWithBytes: [uploadFile bytes] length: 196099]];
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:postBody];
[request setValue:[NSString stringWithFormat:@"%d", [postBody length]] forHTTPHeaderField:@"Content-Length"];
NSLog(@"Uploaded POST size: %d", [postBody length] );

回答1:

Ah, I've found what the issue is. Connection: Keep-alive is being set, even though I set connection: close. How do I override this?? It looks like you can't!?



回答2:

I have following code that is tested for 30-40 MB of files, and it never hangs. It looks almost similar to your code, however are you sure that its not your server side scrip that may be waiting for something?

url = [NSURL URLWithString:u];

NSData* d = [self data];

request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval: 2000 ];
[request setHTTPMethod:@"POST"];
[request setValue:
 [NSString stringWithFormat:@"multipart/form-data; boundary=%@", BOUNDRY]
forHTTPHeaderField:@"Content-Type"];

NSMutableData *postData =
[NSMutableData dataWithCapacity:[d length] + 512];
[postData appendData:
 [[NSString stringWithFormat:@"--%@\r\n", BOUNDRY] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:
 [[NSString stringWithFormat:
   @"Content-Disposition: form-data; name=\"%@\"; filename=\"file.bin\"\r\n\r\n", FORM_FLE_INPUT]
  dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:d];
[postData appendData:
 [[NSString stringWithFormat:@"\r\n--%@--\r\n", BOUNDRY] dataUsingEncoding:NSUTF8StringEncoding]];

[request setHTTPBody:postData];


回答3:

I think you can try to remove this line of codes.

[request addValue:@"close" forHTTPHeaderField: @"Connection"];

It will tell the http server to close this connection. By the RFC 2616 (HTTP/1.1), servers and clients should maintain persistent connection.