有了上一篇文章的鋪墊直接上代碼,下面是分析原理.app
// ViewController.m // 大文件下載 // Created by apple on 15/11/11. // Copyright © 2015年 LDSmallCat. All rights reserved. #import "ViewController.h" #import "DACircularProgressView.h"//進度條的第三方框架 @interface ViewController ()<NSURLConnectionDataDelegate> //下載和暫停按鈕 @property (weak, nonatomic) IBOutlet UIButton *button; //用來寫數據的文件句柄對象 @property(nonatomic,strong) NSFileHandle *writeHandle; //文件的總大小.用已經下載的進度 除以 文件的總大小,作出進度條 @property(nonatomic,assign) long long totalLength; //當前已經寫入的文件大小.已經下載的, @property(nonatomic,assign) long long currentLength; ///連接對象 @property (nonatomic, strong) NSURLConnection *conn; //進度條 @property(nonatomic,weak) DACircularProgressView * circleView; @end @implementation ViewController - (void)viewDidLoad{ [super viewDidLoad]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ NSLog(@"didFailWithError"); } //接收到響應就會調用 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ //下載完成後 再次點擊的時候,若是爲1就直接返回,不在下載,或彈框告訴用戶已經存在, //須要將self.currentLength寫入本地文件才能作到不會重複下載.就是說這個程序沒法避免重複下載 if (self.currentLength) return; //數據保存的路徑 NSString * caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString * filepath = [caches stringByAppendingPathComponent:@"download2.mp4"]; //經過這個路徑建立一個文件 到 沙盒中 NSFileManager * mgr = [NSFileManager defaultManager]; [mgr createFileAtPath:filepath contents:nil attributes:nil]; //建立一個用來寫入文件數據的文件句柄 self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath]; //獲取文件總大小 self.totalLength = response.expectedContentLength; NSLog(@"didReceiveResponse文件總大小%lld",self.totalLength); } //接受到數據就會調用,若是數據很大會被調用屢次.邊下邊存儲到沙盒,不會有內存問題 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ //移動到文件的最後面 [self.writeHandle seekToEndOfFile]; //數據寫入沙盒 [self.writeHandle writeData:data]; //累計文件長度,經過循環不斷增大這個值,在下面的方法中拿到這個值量化去下載任務 //好比這裏第一次拿到300字節,下面請求下載0-300的任務,下次拼接後爲1000,下面請求下載300-1000 //的任務, self.currentLength += data.length; self.circleView.progress = (double)self.currentLength / self.totalLength; //通過不斷拼接,已經寫入的數據, NSLog(@"didReceiveData 已經下載的數據%lld ",self.currentLength); } //下載完成後調用,作些處理工做 - (void)connectionDidFinishLoading:(NSURLConnection *)connection{ //變量歸零 self.currentLength = 1; self.totalLength = 0; //關閉文佳 [self.writeHandle closeFile]; self.writeHandle = nil; } - (IBAction)downLoad:(UIButton *)sender{ //狀態取反 sender.selected = ! sender.selected; //斷點續傳,斷點下載 if(sender.selected){ //1.點擊下載,建立URL,發送請求.url中不能有中文 NSURL * url = [NSURL URLWithString:@"http://localhost/dawenjianyasuo.zip"]; //2.請求 NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url]; self.currentLength = 0; //設置請求頭.實現的要點在這裏,此處的Rang屬性實現了下載的控制,用self.currentLength //來保存已經下載了多少字節, NSString * range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLength]; [request setValue:range forHTTPHeaderField:@"Range"]; //下載(建立完conn對象後,會自動發起一個異步請求)
self.conn = [NSURLConnection connectionWithRequest:request delegate:self]; }else{//一旦點擊暫停建立的request就會銷燬,再次點擊下載時須要從新建立. [self.conn cancel]; self.conn = nil; } } @end
總體流程:框架
原理會在下一篇文章中說明,異步