简体   繁体   English

Objective-C部分下载的文件以及如何清理内存

[英]Objective-C partially downloaded file and how can i clean memory

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. 该函数向服务器发送请求以获取静态文件的一部分,例如50MB的字节= 50000000-100000000“。

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? 循环的每个迭代结束时如何清除内存?

What you want to do is wrap the code inside the loop in an autorelease pool: 您要做的是将代码包装在循环中的自动释放池中:

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/memorymgmt/articles/mmAutoreleasePools.html https://developer.apple.com/library/mac/documentation/cocoa/conceptual/memorymgmt/articles/mmAutoreleasePools.html

When execution exits the auto-release pool, memory that can be freed by ARC should be. 当执行退出自动释放池时,应该可以释放ARC的内存。

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: 但是,如果您切换为立即使用NSOutputStream异步下载整个文件, NSOutputStream按照此问题的答案使用更少的代码,并且不占用线程:

Downloading a Large File - iPhone SDK 下载大文件-iPhone SDK

You still may want to stick with your mechanism as it lets the server operate with smaller chunks to send. 您可能仍要坚持使用您的机制,因为它允许服务器使用较小的块进行操作以进行发送。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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