Big File Download Considerations
- If you do not dump the downloaded files, it will cause a sharp increase in memory consumption, or even run out of memory resources, causing the program to terminate.
- In the file download process usually occurs midway stop situation, if not to do processing, it is necessary to restart the download, waste traffic.
Solutions for large file downloads
- Process the downloaded files, write the data to disk (usually in a sandbox), and avoid accumulating data in memory (nsurlconnection download), with every bit of data downloaded
- Implementing write Data using the Nsfilehandle class
- Implementing write Data using the Nsoutputstream class
- When the download task terminates, log the location information at the end of the task so that the next time you start the download
Large file Download (nsurlconnection)
- Breakpoint Download not supported
- Download files using the Nsurlconnection proxy method
- The task of transferring the downloaded file and recording the end location in the proxy method of the callback at different stages of the download task
To use the Nsfilehandle class to implement the download procedure for writing data ( 完整核心代码
)
- Set related member properties
/**所要下载文件的总长度*/@property (nonatomic, assign) NSInteger contentLength;/**已下载文件的总长度*/@property (nonatomic, assign) NSInteger currentLength/**文件句柄,用来实现文件存储*/@property (nonatomic, strong) NSFileHandle *handle;
// 1. 创建请求路径NSURL *url = [NSURL URLWithString:@"此处为URL字符串"];// 2. 将URL封装成请求NSURLRequest *request = [NSURLRequest requestWithURL:url];// 3. 通过NSURLConnection,并设置代理[NSURLConnection connectionWithRequest:request delegate:self];
- Comply with Agent protocol Nsurlconnectiondatadelegate, implement proxy method
/*** The method that is called when the server response is received * /- (void) Connection: (Nsurlconnection *) connection didreceiveresponse: (Nshttpurlresponse *) response{//Get the total length of the file you want to downloadSelf.contentlength = [response.allheaderfields[@"Content-length"] IntegerValue];//Stitching a file path in a sandboxNSString *filepath = [[Nssearchpathfordirectoriesindomains (Nscachesdirectory, Nsuserdomainmask, YES) LastObject] stringbyappendingpathcomponent:@"Minion_15.mp4"];//Create a file of the specified path[[Nsfilemanager Defaultmanager] Createfileatpath:filepath contents:nil Attributes:nil];//Create file handleSelf.handle = [Nsfilehandle filehandleforwritingatpath:filepath];}/*** the method to call when receiving data from the server * /- (void) Connection: (Nsurlconnection *) connection didreceivedata: (NSData *) data{//Navigate to the end of the file and stitch the file data returned by the server to the end of the file each time[Self.handle Seektoendoffile];//through file handle, write file to sandbox[Self.handle Writedata:data];//Stitching The total length of downloaded filesSelf.currentlength + = Data.length;//Calculate Download ProgressCGFloat progress =1.0* SELF.CURRENTLENGTH/SELF.CONTENTLENGTH;}/*** The method that is called when the file is downloaded * /- (void) Connectiondidfinishloading: (nsurlconnection *) connection{//Close the file handle and clear[Self.handle CloseFile]; Self.handle = nil;//Empty downloaded file lengthSelf.currentlength =0;}
To use the Nsoutputstream class to implement the download procedure for writing data ( 部分代码,其他部分代码同上
)
- Set Nsoutputstream member properties
@property (nonatomicstrong) NSOutputStream *stream;
- Initialize the Nsoutputstream object to open the output stream
/**接收到服务器响应的时候调用*/- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ //获取下载数据保存的路径 NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *filePath = [cache stringByAppendingPathComponent:response.suggestedFilename]; //利用NSOutputStream往filePath文件中写数据,若append参数为yes,则会写到文件尾部 self.stream = [[NSOutputStream alloc] initToFileAtPath:filePath append:YES]; //打开数据流 [self.stream open];}
/**接收到数据的时候调用*/- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ [self.stream write:[data bytes] maxLength:data.length];}
- Turn off the output stream
/**数据下载完毕的时候调用*/- (void)connectionDidFinishLoading:(NSURLConnection *)connection{ [self.stream close];}
Large file Download (nsurlsession)
- Support breakpoint download, automatically record the location of breakpoints when stopping download
- Compliance with Nsurlsessiondownloaddelegate Protocol
- Using nsurlsession to download large files, the downloaded files will be automatically written to the sandbox Temp folder tmp
- After downloading, it is usually necessary to move the downloaded files elsewhere (the data in the TMP folder is deleted periodically), usually in the cache folder
Detailed download steps
- Set Download task task as member variable
@property (nonatomicstrong) NSURLSessionDownloadTask *task;
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
- Initializing the Download Task task
self.task = [session downloadTaskWithURL:(此处为下载文件路径URL)];
- Implementing Proxy methods
/** Each time the data is written to a temporary file, the method is called once, usually in this method to get the download progress * /- (void) Urlsession: (Nsurlsession *) session Downloadtask: (Nsurlsessiondownloadtask *) downloadtask didwritedata: (int64_t) Byteswritten Totalbyteswritten: (int64_t) Totalbyteswritten totalbytesexpectedtowrite: (int64_t) totalbytesexpectedtowrite{//Calculate Download ProgressCGFloat progress =1.0* Totalbyteswritten/totalbytesexpectedtowrite;}/** The method that is called when the task terminates, usually for a breakpoint download * /- (void) Urlsession: (Nsurlsession *) session Downloadtask: (Nsurlsessiondownloadtask *) Downloadtask Didresumeatoffset: (Int64 _t) Fileoffset expectedtotalbytes: (int64_t) expectedtotalbytes{//fileoffset: The offset when the download task is aborted}/** is called when an error is encountered, the error parameter can only pass client-side errors * /- (void) Urlsession: (Nsurlsession *) session Task: (Nsurlsessiontask *) Task Didcompletewitherror: (Nserror *) error{}/** When the download is complete, you need to cut the file into a folder that can be saved for a long time * /- (void) Urlsession: (Nsurlsession *) session Downloadtask: (Nsurlsessiondownloadtask *) downloadtask Didfinishdownloadingtourl: (Nsurl *) location{//Generate files for long-term saved pathsNSString *file = [[Nssearchpathfordirectoriesindomains (Nscachesdirectory, Nsuserdomainmask, YES) LastObject] StringByAppendingPathComponent:downloadTask.response.suggestedFilename];//Get file handleNsfilemanager *filemanager = [Nsfilemanager Defaultmanager];//Through the file handle, cut the file to the long-term saved path of the file[FileManager moveitematurl:location Tourl:[nsurl fileurlwithpath:file] error:nil];}
/**开始/继续下载任务*/[self.task resume];/**暂停下载任务*/[self.task suspend];
The latest status of this blog will be synced to Sina Weibo account: secular island
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
iOS network -04-large file download