简体   繁体   中英

What is the correct way of sending large file through HTTP POST, without loading the whole file into ram?

I'm currently working on an application for uploading large video files from the iPhone to a webservice through simple http post. As of right now, I build an NSURLRequest and preload all of the video file data before loading the request. This naturally eats a ton of ram if the file is considerably big, in some cases it's not even possible.

So basically my question is: Is there a correct way of streaming the data or loading it in chunks without applying any modifications to the webserver?

Thanks.

EDIT for clarification: I am searching for a way to stream large multipart/form data FROM the iPhone TO a webserver. Not the other way arround.

EDIT after accepting answer: I just found out that apple has some nifty source code written for this exact purpose and it shows appending additional data to the post not just the big file itself. Incase anyone ever needs it: SimpleURLConnections - PostController.m

Yet another EDIT: While using that piece of source code from apple I encountered a very stupid and ugly problem that even wireshark couldn't help me debug. Some webservers don't understand the boundary string when it's declared in between quotes (like in apples example). I had problems with it on Apache Tomcat and removing the quotes worked just wonderful.

You can use NSInputStream on NSMutableURLRequest . For example:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:uploadURL];
NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:filePath];
[request setHTTPBodyStream:stream];
[request setHTTPMethod:@"POST"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    NSLog(@"Finished with status code: %i", [(NSHTTPURLResponse *)response statusCode]);
}];

You can use a NSInputStream to provide the data to post via -[NSMutableURLRequest setHTTPBodyStream:] . This could be an input stream that reads from a file. You might need to implement the connection:needNewBodyStream: method in your URL connection delegate to provide a new, unopened stream in case the system needs to retransmit the data.

One way to do this is to use an asynchronous NSInputStream in concert with a file. When the asynchronous connection asks you to provide more data, you read in the data from a file. You have a few ways to do this:

  • UNIX/BSD interface. use open (or fopen), malloc, read, and create a NSData object from the malloced data

  • use the above with mmap() if you know it

  • use the Foundation class NSFileHandle APIs to do more or less the same using ObjectiveC

You can read up on streams in the 'Stream Programming Guide'. If this doesn't work for you there are lots of open source projects that can upload files, for instance MKNetworkKit

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM