osx - NSMutableURLRequest and memory issue -
good morning, i'm developing application uploads files; there no real issues, 1 big problem: if try upload 1gb of files allocates 1gb of memory, , can understand not thing.
here's code: allocate data nsdata , use nsmutableurlrequest + nsurlconnection upload them; question is: there ways without needing allocate whole memory? i've searched out, found nothing...
_uploaddatafile nsdata sub-class instance allocated before.
nsmutableurlrequest *request = [[[nsmutableurlrequest alloc] initwithurl:[nsurl urlwithstring:@"http://my.server/page"] cachepolicy:nsurlrequestreloadignoringcachedata timeoutinterval:60.0] autorelease]; nsdata *datafile; if (_uploaddatafile == nil) { nserror *error = nil; datafile = [[[nsdata alloc] initwithcontentsoffile:@"pathtofile" options:nsdatareadinguncached error:&error] autorelease]; if (error) { nslog(@"error %i: %@", [error code], [error localizeddescription]); [self fermaupload]; //stop upload return; } } else datafile = [_uploaddatafile file]; nsmutabledictionary *dictpost = [[[nsmutabledictionary alloc] init] autorelease]; [dictpost setvalue:datafile forkey:@"uploads[]"]; nsdata *mutdata = [self dataforpostwithdictionary:dictpost boundary:@"0194784892923" nomefile:[@"pathtofile" lastpathcomponent]]; nsstring *postlength = [nsstring stringwithformat:@"%d", [mutdata length]]; [request sethttpmethod:@"post"]; [request setvalue:postlength forhttpheaderfield:@"content-length"]; [request setvalue:@"multipart/form-data; boundary=0194784892923" forhttpheaderfield:@"content-type"]; [request sethttpbody:mutdata]; [request sethttpshouldhandlecookies:yes]; theconnection = [[nsurlconnection alloc] initwithrequest:request delegate:self];
and here's how - (nsdata *)dataforpostwithdictionary:boundary:nomefile: method looks like:
- (nsdata *)dataforpostwithdictionary:(nsdictionary *)adictionary boundary:(nsstring *)aboundary nomefile:(nsstring *)nomefile { nsarray *mydictkeys = [adictionary allkeys]; nsmutabledata *mydata = [nsmutabledata datawithcapacity:1]; nsstring *myboundary = [nsstring stringwithformat:@"--%@\r\n", aboundary]; for(int = 0;i < [mydictkeys count];i++) { id myvalue = [adictionary valueforkey:[mydictkeys objectatindex:i]]; [mydata appenddata:[myboundary datausingencoding:nsutf8stringencoding]]; //if ([myvalue class] == [nsstring class]) { if ([myvalue iskindofclass:[nsstring class]]) { [mydata appenddata:[[nsstring stringwithformat:@"content-disposition: form-data; name=\"%@\"\r\n\r\n", [mydictkeys objectatindex:i]] datausingencoding:nsutf8stringencoding]]; [mydata appenddata:[[nsstring stringwithformat:@"%@", myvalue] datausingencoding:nsutf8stringencoding]]; } else if(([myvalue iskindofclass:[nsurl class]]) && ([myvalue isfileurl])) { [mydata appenddata:[[nsstring stringwithformat:@"content-disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", [mydictkeys objectatindex:i], [[myvalue path] lastpathcomponent]] datausingencoding:nsutf8stringencoding]]; [mydata appenddata:[[nsstring stringwithformat:@"content-type: application/octet-stream\r\n\r\n"] datausingencoding:nsutf8stringencoding]]; [mydata appenddata:[nsdata datawithcontentsoffile:[myvalue path]]]; } else if(([myvalue iskindofclass:[nsdata class]])) { [mydata appenddata:[[nsstring stringwithformat:@"content-disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", [mydictkeys objectatindex:i], nomefile] datausingencoding:nsutf8stringencoding]]; [mydata appenddata:[[nsstring stringwithformat:@"content-type: application/octet-stream\r\n\r\n"] datausingencoding:nsutf8stringencoding]]; [mydata appenddata:myvalue]; } // eof if() [mydata appenddata:[[nsstring stringwithstring:@"\r\n"] datausingencoding:nsutf8stringencoding]]; } // eof for() [mydata appenddata:[[nsstring stringwithformat:@"--%@--\r\n", aboundary] datausingencoding:nsutf8stringencoding]]; return mydata; } // eof dataforpostwithdictionary:boundary:
thank , sorry english.
a interesting problem! there 2 ways of feeding body data nsurlconnection/request
:
nsdata
nsinputstream
unfortunately, neither want out of box, since want upload file + form data. ideally, subclass nsinputstream
provide data formatted require. however, last time checked, nsurlconnection
unable handle such subclasses. instead, like:
- create pair of streams using
cfstreamcreateboundpair()
. returnscfwritestream
,cfreadstream
, toll-free bridgednsoutputstream
,nsinputstream
, respectively - set output stream's delegate
-sethttpbodystream:
on url request input stream- start connection
the output stream's delegate should called periodically, requesting data. need feed in post data, followed chunks of file data. entire file never entirely in memory @ once.
Comments
Post a Comment