NSURLSessionDataTask for iOS development enables offline breakpoint download of large files (important ),

Source: Internet
Author: User

NSURLSessionDataTask for iOS development enables offline breakpoint download of large files (important ),

NSURLSessionDataTask for iOS development enables offline breakpoint download of large files (important ). Source code download: https://github.com/coderZYGui/ZYBreakpointDownload

As follows:

Knowledge point:

1.Obtain the file size corresponding to the specified file path (the file data size that has been downloaded)

2.(Resumable download idea) Use NSMutableURLRequest to create a variable request. set the request header information to tell the server which part of the data is requested (the data after the request has been downloaded (Knowledge Point 1, the size of the file data already downloaded in)

 

// You can set the Range attribute of the HTTP request header to download the first 500 bytes starting from the specified position: Range: bytes = 0-499 indicates the second 500 bytes: Range: bytes = 500-999 indicates the last 500 bytes: Range: bytes =-500 indicates the Range after 500 bytes: Range: bytes = 500-
3.Use response. expectedContentLength to obtain the total file data size of this request.

 

Note:

File data size of this request! = Total file size (response. expectedContentLength is the file size. If the request is sent again, the self. totalSize is smaller than the file size. Therefore, 1.0 * self is calculated later. currentSize/self. when totalSize is used, data is disordered. Therefore, you must add the downloaded data.

4.In the proxy method that receives the server response, the request is canceled by default. The enumerated value is NSURLSessionResponseAllow.

CompletionHandler (NSURLSessionResponseAllow );

 

5.Judge the downloaded data self. currentSize = 0 to create an empty file. prevent multiple Empty files from being created when multiple requests are sent, resulting in file data size disorder.

 

6.Use the file handle to splice the downloaded data. [self. handle seekToEndofFile];

 

7.Save the total and downloaded file data to the sandbox. When the program runs, set the downloaded data/total file data to the value of the slider.

 

8.Release NSURLSession object

 

-(Void) dealloc {// if the session sets a proxy, there will be a strong reference. will not be released. therefore, release the session object: Call the following two methods. \ otherwise, memory leakage may occur. // finishTasksAndInvalidate [self. session invalidateAndCancel];}

 

Code:

 

// Created by Chaoyang on April /12/19. // Copyright©Sunny. All rights reserved. // # import "ViewController. h" # define FileName @ "zy.mp4" @ interface ViewController ()
 
  
@ Property (nonatomic, strong) NSFileHandle * handle; @ property (nonatomic, assign) NSInteger totalSize; @ property (nonatomic, assign) NSInteger currentSize; @ property (nonatomic, strong) NSString * fullPath; @ property (weak, nonatomic) IBOutlet UISlider * slider; @ property (nonatomic, strong) nsurlsessionask ask * dataTask; @ property (nonatomic, strong) NSURLSession * session; @ end @ implementation ViewController -(Void) viewDidLoad {[super viewDidLoad]; // set the slider progress to 1.0 * downloaded file size/total file size self. slider. value = [self getSandboxFileSize]; if (self. slider. value == 1.0) {self. slider. value = 0 ;}- (CGFloat) getSandboxFileSize {// 1. read the total file size saved in the sandbox NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; NSNumber * totalFileSize = [defaults objectForKey: @ "fileSize"]; NSNumber * currentFileSize = [def Aults objectForKey: @ "currentFileSize"]; NSInteger totalSize = [totalFileSize integerValue]; NSInteger currentSize = [currentFileSize integerValue]; NSLog (@ "% ld", totalSize ); NSLog (@ "% ld", currentSize); return 1.0 * currentSize/totalSize;} # pragma-mark lazy loading-(NSURLSession *) session {if (! _ Session) {// create a session object and set proxy _ session = [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration] delegate: self delegateQueue: [NSOperationQueue mainQueue];} return _ session;}-(NSString *) fullPath {if (! _ FullPath) {// 2. obtain the full file path _ fullPath = [[callback (NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingString: FileName];} return _ fullPath;}-(NSURLSessionDataTask *) dataTask {if (! _ DataTask) {// 1. url NSURL * url = [NSURL URLWithString: @ "https://flv2.bn.netease.com/videolib3/1604/28/fVobI0704/SD/fVobI0704-mobile.mp4"]; // 2. create a request object NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL: url]; // obtain the file size (the size of the downloaded file) self. currentSize = [self getFileSize]; NSLog (@ "currentSize ---- ++ ---- % ld", self. currentSize); // 2.1 sets the request header to tell the server which part of the data requested (the current Data after the uploaded data) // you only need to set the Range attribute of the HTTP request header to download the data starting from the specified position./* indicates the first 500 Bytes: Range: bytes = 0-499 indicates the second 500 byte: Range: bytes = 500-999 indicates the last 500 bytes: Range: bytes =-500 indicates the Range after 500 bytes: Range: bytes = 500-*/NSString * range = [NSString stringWithFormat: @ "bytes = % zd-", self. currentSize]; [request setValue: range forHTTPHeaderField: @ "Range"]; // 3. create a Task _ dataTask = [self. session dataTaskWithRequest: request];} return _ dataTask;} // Obtain the file size corresponding to the specified file path-(NSInteger) getFileSize {NSDictionary * fileInfoDict = [[NSFileManager defaultManager] attributesOfItemAtPath: self. fullPath error: nil]; NSLog (@ "% @", fileInfoDict); // obtain the file information in the dictionary-file size // currentSize = self. currentSize; NSInteger currentSize = [fileInfoDict [@ "NSFileSize"] integerValue]; return currentSize ;}- (IBAction) startDwonload :( id) sender {NSLog (@ "++ start download"); // 5. run Task [self. dataTask resume];}-(IBAction) supendDownload :( id) sender {NSLog (@ "++ pause download "); [self. dataTask suspend];} // cancel Method: resumable download-(IBAction) cancelDownload :( id) sender {NSLog (@ "++ cancel download"); [self. dataTask cancel]; // clear dataTask. in resumeDownload: method, self. the dataTask method is self. dataTask = nil;} // resume download-(IBAction) resumeDownload :( id) sender {NSLog (@ "++ resume download"); [self. data Task resume];} # pragma-mark NSURLSessionDataDelegate/** receives the server response. By default, this request @ param session object @ param dataTask request Task @ param response header information @ param completionHandler is called back and passed system */-(void) URLSession :( NSURLSession *) session dataTask :( NSURLSessionDataTask *) dataTask didReceiveResponse :( NSURLResponse *) response completionHandler :( void (^) (response) completionHandler {// 0. get the total size of the file (this Total size of the file data in the request) // size of the file data in the request! = Total file size (if the request is sent again, the self. totalSize is smaller than the file size. Therefore, 1.0 * self is calculated after. currentSize/self. when totalSize is used, data is disordered. Therefore, you must add the downloaded data. self. totalSize = response. expectedContentLength + self. currentSize; // Add the total file case to the sandbox NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject: @ (self. totalSize) forKey: @ "fileSize"];/* NSURLSessionResponseCancel = 0, cancel NSURLSessionResponseAllow = 1 by default, receive NSURLSessionResponseBecomeDownload = 2, convert the download task into a stream * // 1. because the system cancels the task request by default. therefore, you need to set the enumeration to receive completionHandler (NSURLSessionResponseAllow); // If the currently downloaded data is 0. create an empty file (to prevent file size disorder due to multiple Empty files) if (self. currentSize = 0) {// 3. create an empty file (write the file to the sandbox) [[NSFileManager defaultManager] createFileAtPath: self. fullPath contents: nil attributes: nil];} // 4. create File handle self. handle = [NSFileHandle fileHandleForWritingAtPath: self. fullPath]; // 5. after the data is downloaded, splice [self. handle seekToEndOfFile];}/** receives the data returned by the server and calls it multiple times @ param session object @ param dataTask request Task @ param data the data downloaded this time */-(void) URLSession :( NSURLSession *) session dataTask :( NSURLSessionDataTask *) dataTask didReceiveData :( NSData *) data {// 1. write Data to the file [self. handle writeData: data]; // 2. concatenate downloaded data self. currentSize + = data. length; // Add the downloaded file to the sandbox in case of NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject: @ (self. currentSize) forKey: @ "currentFileSize"]; // 3. download progress NSLog (@ "% f", 1.0 * self. currentSize/self. totalSize); self. slider. value = 1.0 * self. currentSize/self. totalSize;}/** call @ param session object @ param task when the request ends or fails */-(void) URLSession :( NSURLSession *) session task :( NSURLSessionTask *) task didCompleteWithError :( NSError *) error {// 1. close the file handle [self. handle closeFile]; self. handle = nil; NSLog (@ "% @", self. fullPath);}-(void) dealloc {// if the session sets proxy, there will be a strong reference. will not be released. therefore, release the session object: Call the following two methods. \ otherwise, memory leakage may occur. // finishTasksAndInvalidate [self. session invalidateAndCancel];} @ end
 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.