Reputation:
I have a problem.
My function must download extra large files piecemeal.
The function sends request to server to get part of a static file - for example bytes=50000000-100000000" in 50MB pieces.
The code concatenates all pieces in one file, so that it does overflow memory downloading.
But i have a problem - memory is not freed in each loop cycle, it just keeps adding up.
NSData *data;
NSOutputStream *stream;
NSString *savePath;
NSMutableURLRequest *request;
NSHTTPURLResponse *response;
int downloadingLimitBlock=50000000;//50MB
int downloadingFileFullSize=0;
int fIndex=0;//tmp
//
//
count=1;//count will changed if size more then minimum size
for (i = 0; i < count; i++)
{
savePath=[NSString stringWithFormat:@"%@%@", videoContentFolderPath,[videoFilesNamesServerList objectAtIndex: fIndex]];//финдекс
stream = [[NSOutputStream alloc] initToFileAtPath:savePath append:YES];
[stream open];
request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[videoFilesServerList objectAtIndex: fIndex]]];//финдекс
[request setValue:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71" forHTTPHeaderField:@"User-Agent"];
[request setValue:[NSString stringWithFormat: @"bytes=%d-%d",(((i+1)*downloadingLimitBlock)-downloadingLimitBlock),(((i+1)*downloadingLimitBlock)-1)] forHTTPHeaderField:@"Range"];
data = [NSURLConnection sendSynchronousRequest:request returningResponse: &response error: nil ];
NSLog(@"bytes=%d-%d",(((i+1)*downloadingLimitBlock)-downloadingLimitBlock),(((i+1)*downloadingLimitBlock)-1));
switch (response.statusCode) {
case 206: {
NSString *headerContentRange = [response.allHeaderFields valueForKey:@"Content-Range"];
NSArray *tmpArray=[headerContentRange componentsSeparatedByString:@"/"];
downloadingFileFullSize=[[tmpArray objectAtIndex:1] integerValue];
//recalculate count
count=ceil(downloadingFileFullSize/downloadingLimitBlock)+1;
//recalculate count
NSLog(@"Status code 206 OK");
NSLog(@"sizefromserver %d",downloadingFileFullSize);
break;
}
case 200: {
downloadingFileFullSize = [[response.allHeaderFields valueForKey:@"Content-Length"] integerValue];
NSLog(@"sizefromserver %d",downloadingFileFullSize);
[self logIt:@"Warning! Maybe server is not supporting partly download static content, server returns status code 200, but must 206" ];
///Need add link to server too in logIt
break;
}
default: {
[self logIt:[NSString stringWithFormat:@"Error! while loading video content file,status code is %ld",(long)response.statusCode]];
///Need add link to server too in logIt
break;
}
}
NSUInteger left = [data length];
NSLog(@"part %d lenght %lu",i,(unsigned long)left);
NSUInteger nwr = 0;
do {
nwr = [stream write:[data bytes] maxLength:left];
if (-1 == nwr) break;
left -= nwr;
} while (left > 0);
if (left) {
NSLog(@"stream error: %@", [stream streamError]);
}
[stream close];
data=nil;
stream=nil;
}
//////////////
LOG:
2013-12-29 00:18:38.890 RAT[151:60b] bytes=0-49999999
2013-12-29 00:18:38.892 RAT[151:60b] Status code 206 OK
2013-12-29 00:18:38.893 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:18:38.894 RAT[151:60b] part 0 lenght 50000000
2013-12-29 00:19:07.624 RAT[151:60b] bytes=50000000-99999999
2013-12-29 00:19:07.626 RAT[151:60b] Status code 206 OK
2013-12-29 00:19:07.627 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:19:07.628 RAT[151:60b] part 1 lenght 50000000
2013-12-29 00:19:52.253 RAT[151:60b] bytes=100000000-149999999
2013-12-29 00:19:52.255 RAT[151:60b] Status code 206 OK
2013-12-29 00:19:52.256 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:19:52.257 RAT[151:60b] part 2 lenght 50000000
2013-12-29 00:20:18.133 RAT[151:60b] bytes=150000000-199999999
2013-12-29 00:20:18.134 RAT[151:60b] Status code 206 OK
2013-12-29 00:20:18.135 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:20:18.136 RAT[151:60b] part 3 lenght 50000000
2013-12-29 00:20:40.666 RAT[151:60b] bytes=200000000-249999999
2013-12-29 00:20:40.667 RAT[151:60b] Status code 206 OK
2013-12-29 00:20:40.668 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:20:40.669 RAT[151:60b] part 4 lenght 50000000
2013-12-29 00:21:04.930 RAT[151:60b] bytes=250000000-299999999
2013-12-29 00:21:04.931 RAT[151:60b] Status code 206 OK
2013-12-29 00:21:04.932 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:21:04.933 RAT[151:60b] part 5 lenght 50000000
2013-12-29 00:21:26.906 RAT[151:60b] bytes=300000000-349999999
2013-12-29 00:21:26.907 RAT[151:60b] Status code 206 OK
2013-12-29 00:21:26.908 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:21:26.909 RAT[151:60b] part 6 length 50000000
And out of memory
How can I clear memory when each iteration of the loop ends?
Upvotes: 1
Views: 509
Reputation: 75058
What you want to do is wrap the code inside the loop in an autorelease pool:
When execution exits the auto-release pool, memory that can be freed by ARC should be.
Basically it would look like:
for (i = 0; i < count; i++)
{
@autoreleasepool
{
// All the code from the loop
}
}
However you could use a lot less code, and not tie up a thread if you switch to downloading the whole file at once asynchronously using NSOutputStream
as per the answer to this question:
Downloading a Large File - iPhone SDK
You still may want to stick with your mechanism as it lets the server operate with smaller chunks to send.
Upvotes: 2