Network Programming for iOS development-4. NSURLSessionDataTask for file download (offline resumable download) & lt; Progress value display optimization & gt;, nsurlsession resumable download

Source: Internet
Author: User

Network Programming for iOS development-4. NSURLSessionDataTask implements file download (offline resumable download) <progress value display optimization> and nsurlsession resumable download

According to the previous article "network programming for iOS development-2. NSURLSessionDownloadTask File Download" or "network programming for iOS development-3. NSURLSessionDataTask File Download (offline resumable download)", there is an unsolved problem left over, that is, when the application restarts during the offline breakpoint download process, the progress value of the progress bar is not set to the progress that has been downloaded by default. According to the basic formula, "current progress value = the length of the downloaded data; the total length of the downloaded data ", the downloaded data length can be obtained from the downloaded data in the sandbox. However, the total length of the downloaded data must be returned through the network, the initial state of each restart application is paused by default, or network data cannot be requested when the application is disconnected. How can I get the "Total length of the downloaded data?

First look at the effect:

Solution: "The total length of the final downloaded data" can be obtained through the network when the first download starts from 0, then, store the value "total length of the downloaded data" in a cached file (this file can be a dictionary, etc.) and wait for the next retrieval.

The method I used is to add the "Total data length after the final download" as the file attribute to the file attribute list for the next read, after obtaining this file, you can read "The Final download is complete" from the property list of the file.

Total length of data "attributes and attribute values.

I have to introduce a tool class here. You can use another blog post to learn about its function first: iOS development-a tool class that adds custom attributes to local files.

After adding attributes to a local file, you can print the following information:

I spent some time encapsulating this part of web download into a tool class: DownloadTool. The following shows the source code:

DownloadTool. h

1 # import <Foundation/Foundation. h> 2 3 4 // define a block to pass the progress value 5 typedef void (^ SetProgressValue) (float progressValue); 6 7 @ interface DownloadTool: NSObject 8 9/** create download Tool Object */10 + (instancetype) DownloadWithURLString :( NSString *) urlString setProgressValue :( SetProgressValue) setProgressValue; 11/** start download */12-(void) startDownload; 13/** pause download */14-(void) suspendDownload; 15 16 @ end

DownloadTool. m

1 # import "DownloadTool. h "2 3 # import" ExpendFileAttributes. h "4 5 # define Key_FileTotalSize @" Key_FileTotalSize "6 7 @ interface DownloadTool () <NSURLSessionDataDelegate> 8/** Session */9 @ property (nonatomic, strong) NSURLSession * session; 10/** Task task */11 @ property (nonatomic, strong) NSURLSessionDataTask * Task; 12/*** file full path */13 @ property (nonatomic, strong) NSString * fileFullPath; 14 /** Block */15 @ property (nonatomic, copy) SetProgressValue setProgressValue; 16/** length of the currently downloaded file */17 @ property (nonatomic, assign) NSInteger currentFileSize; 18/** output stream */19 @ property (nonatomic, strong) NSOutputStream * outputStream; 20/*** unchanged total file length */21 @ property (nonatomic, assign) NSInteger fileTotalSize; 22 @ end 23 24 @ implementation DownloadTool 25 26 + (instancetype) DownloadWithURLString :( NS String *) urlString setProgressValue :( SetProgressValue) setProgressValue {27 DownloadTool * download = [[DownloadTool alloc] init]; 28 download. setProgressValue = setProgressValue; 29 [download getFileSizeWithURLString: urlString]; 30 [download creatDownloadSessionTaskWithURLString: urlString]; 31 NSLog (@ "% @", download. fileFullPath); 32 return download; 33} 34 // when you just created the tool class for downloading the network, you need to query whether a local file has been downloaded and return The downloaded length is 35-(void) getFileSizeWithURLString :( NSString *) urlString {36 // create a file manager 37 NSFileManager * fileManager = [NSFileManager defamanager]; 38 // get all parts of the file 39 NSArray * fileComponents = [fileManager componentsToDisplayForPath: urlString]; 40 // get the downloaded file name 41 NSString * fileName = [fileComponents lastObject]; 42 // splice the sandbox full path 43 NSString * fileFullPath = [[NSSearchPathForDirectoriesInDomains (NSCache SDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent: fileName]; 44 self. fileFullPath = fileFullPath; 45 46 NSDictionary * attributes = [fileManager attributesOfItemAtPath: fileFullPath 47 error: nil]; 48 // if the file exists and the download is incomplete, you can directly display the length of the file and set the progress value, and set the length of the current file to 49 NSInteger fileCurrentSize = [attributes [@ "NSFileSize"] integerValue]; 50 // if the file length is 0, you do not need to calculate the progress value of 51 if (fileCurrentSize! = 0) {52 // obtain the final file length 53 NSInteger fileTotalSize = [[ExpendFileAttributes stringValueWithPath: self. fileFullPath key: Key_FileTotalSize] integerValue]; 54 self. currentFileSize = fileCurrentSize; 55 self. fileTotalSize = fileTotalSize; 56 // set the progress bar value 57 self. setProgressValue (1.0 * fileCurrentSize/fileTotalSize); 58} 59 NSLog (@ "current file length: % lf", self. currentFileSize * 1.0); 60} 61 # pragma mark-create a network request Session and task, and start task 62-(void) creatDownloadSessionTaskWithURLString :( NSString *) urlString {63 // determine whether the file has been downloaded 64 if (self. currentFileSize = self. fileTotalSize & self. currentFileSize! = 0) {65 NSLog (@ "the file has been downloaded"); 66 return; 67} 68 NSURLSession * session = 69 [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration] 70 delegate: self 71 delegateQueue: [[NSOperationQueue alloc] init]; 72 NSURL * url = [NSURL URLWithString: urlString]; 73 NSMutableURLRequest * request = [Your requestWithURL: url]; 74 // 2.3 Set Request Header 75 NSString * range = [NSString stringWithFormat: @ "bytes = % zd-", self. currentFileSize]; 76 [request setValue: range forHTTPHeaderField: @ "Range"]; 77 NSURLSessionDataTask * task = [session dataTaskWithRequest: request]; 78 self. session = session; 79 self. task = task; 80} 81 82 # pragma mark-control Download Status 83 // start to download 84-(void) startDownload {85 [self. task resume]; 86} 87 // pause download 88-(void) suspendDownload {89 [self. task suspend]; 90} 91 # pragma mark-NSURLSessionDataDelegate proxy method 92 // The proxy method 93-(void) URLSession :( NSURLSession *) session dataTask :( NSURLSessionDataTask *) dataTask didReceiveResponse: 94 (NSURLResponse *) response completionHandler :( void (^) (NSURLSessionResponseDisposition) completionHandler {95 NSLog (@ "executes the proxy method that receives the response call "); 96 // create the output stream and open the stream 97 NSOutputStream * outputStream = [[NSOutputStream alloc] initToFileAtPath: self. fileFullPath append: YES]; 98 [outputStream open]; 99 self. outputStream = outputStream; 100 // if the length of the downloaded file is equal to 0, you need to write the total length information to the file 101 if (self. currentFileSize = 0) {102 NSInteger totalSize = response. expectedContentLength; 103 NSString * totalSizeString = [NSString stringWithFormat: @ "% ld", totalSize]; 104 [ExpendFileAttributes extendedStringValueWithPath: self. fileFullPath key: Key_FileTotalSize value: totalSizeString]; 105 // do not forget to set the total length of 106 self. fileTotalSize = totalSize; 107} 108 // 109 completionHandler (NSURLSessionResponseAllow); 110} 111 // The proxy method 112-(void) URLSession (NSURLSession *) for receiving data calls *) session dataTask :( NSURLSessionDataTask *) dataTask didReceiveData :( NSData *) data {113 NSLog (@ "executed the proxy method for receiving data calls "); 114 // write data through the output stream 115 [self. outputStream write: data. bytes maxLength: data. length]; 116 // Add the length of the written data to the current downloaded data. The length is 117 self. currentFileSize + = data. length; 118 // set the progress value to 119 NSLog (@ "current file length: % lf, total length: % lf", self. current filesize * 1.0, self. fileTotalSize * 1.0); 120 NSLog (@ "Progress value: % lf", self. currentFileSize * 1.0/self. fileTotalSize); 121 // obtain the master thread 122 NSOperationQueue * mainQueue = [NSOperationQueue mainQueue]; 123 [mainQueue addOperationWithBlock: ^ {124 self. setProgressValue (self. currentFileSize * 1.0/self. fileTotalSize); 125}]; 126} 127 // Method for Data download completion call 128-(void) URLSession :( NSURLSession *) session task :( NSURLSessionTask *) task didCompleteWithError :( NSError *) error {129 // close the output stream and close the strong pointer 130 [self. outputStream close]; 131 self. outputStream = nil; 132 // close session 133 [self. session invalidateAndCancel]; 134 NSLog (@ "% @", [NSThread currentThread]); 135} 136-(void) dealloc {137} 138 @ end

Sample source code:

1 # import "ViewController. h "2 # import" RainbowProgress. h "3 4 # import" DownloadTool. h "5 6 # define MP4_URL_String @" http: // 120.25.226.186: 32812/resources/videos/minion_12.mp4 "7 8 9 @ interface ViewController () 10 @ property (weak, nonatomic) IBOutlet UILabel * showDownloadState; 11/** rainbow progress bar */12 @ property (nonatomic, weak) RainbowProgress * rainbowProgress; 13/** network download Tool Object */14 @ property (nonatomic, strong) DownloadTool * download; 15 @ end16 17 @ implementation ViewController18 19-(void) viewDidLoad {20 [super viewDidLoad]; 21 [self setSelfView]; 22 [self addProgress]; 23 [self addDownload]; 24 25} 26 // enable and disable the network download switch 27-(IBAction) SwitchBtn :( UISwitch *) sender {28 if (sender. isOn) {29 self. showDownloadState. text = @ "Start download"; 30 [self. download startDownload]; 31} else {32 self. showDownloadState. text = @ "Pause download"; 33 [self. download suspendDownload]; 34} 35} 36 # pragma mark-Set Controller View37-(void) setSelfView {38 self. view. backgroundColor = [UIColor blackColor]; 39} 40 # pragma mark-add rainbow progress bar 41-(void) addProgress {42 // create a rainbow progress bar, and start the animation 43 RainbowProgress * rainbowProgress = [[RainbowProgress alloc] init]; 44 [rainbowProgress startAnimating]; 45 [self. view addSubview: rainbowProgress]; 46 self. rainbowProgress = rainbowProgress; 47} 48 # pragma mark-create a network download task 49-(void) addDownload {50 DownloadTool * download = [DownloadTool DownloadWithURLString: MP4_URL_String setProgressValue: ^) {51 self. rainbowProgress. progressValue = progressValue; 52}]; 53 self. download = download; 54} 55 56 # pragma mark-set the status bar style 57-(UIStatusBarStyle) preferredStatusBarStyle {58 return UIStatusBarStyleLightContent; 59} 60 61 @ end

(In the middle of the process, restart the application to check the progress bar and continue the test to start the download and pause the download ):

 

Baidu cloud sharing source code link: http://pan.baidu.com/s/1eRwRkZo password: 787n

Reprinted please indicate the source: http://www.cnblogs.com/goodboy-heyang/p/5200873.html, respect for labor results.

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.