ios大文件下载封装

  1 #import <Foundation/Foundation.h>
  2 
  3 @interface HMFileDownloader : NSObject
  4 /**
  5  * 所需要下载文件的远程URL(连接服务器的路径)
  6  */
  7 @property (nonatomic, copy) NSString *url;
  8 /**
  9  * 文件的存储路径(文件下载到什么地方)
 10  */
 11 @property (nonatomic, copy) NSString *destPath;
 12 
 13 /**
 14  * 是否正在下载(有没有在下载, 只有下载器内部才知道)
 15  */
 16 @property (nonatomic, readonly, getter = isDownloading) BOOL downloading;
 17 
 18 /**
 19  * 用来监听下载进度
 20  */
 21 @property (nonatomic, copy) void (^progressHandler)(double progress);
 22 /**
 23  * 用来监听下载完毕
 24  */
 25 @property (nonatomic, copy) void (^completionHandler)();
 26 /**
 27  * 用来监听下载失败
 28  */
 29 @property (nonatomic, copy) void (^failureHandler)(NSError *error);
 30 
 31 /**
 32  * 开始(恢复)下载
 33  */
 34 - (void)start;
 35 
 36 /**
 37  * 暂停下载
 38  */
 39 - (void)pause;
 40 
 41 @end
 42 
 43 
 44 
 45 #import "HMFileDownloader.h"
 46 
 47 @interface HMFileDownloader() <NSURLConnectionDataDelegate>
 48 /**
 49  * 连接对象
 50  */
 51 @property (nonatomic, strong) NSURLConnection *conn;
 52 
 53 /**
 54  *  写数据的文件句柄
 55  */
 56 @property (nonatomic, strong) NSFileHandle *writeHandle;
 57 /**
 58  *  当前已下载数据的长度
 59  */
 60 @property (nonatomic, assign) long long currentLength;
 61 /**
 62  *  完整文件的总长度
 63  */
 64 @property (nonatomic, assign) long long totalLength;
 65 @end
 66 
 67 @implementation HMFileDownloader
 68 
 69 /**
 70  * 开始(恢复)下载
 71  */
 72 - (void)start
 73 {
 74     NSURL *url = [NSURL URLWithString:self.url];
 75     // 默认就是GET请求
 76     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
 77     // 设置请求头信息
 78     NSString *value = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength];
 79     [request setValue:value forHTTPHeaderField:@"Range"];
 80     self.conn = [NSURLConnection connectionWithRequest:request delegate:self];
 81     
 82     _downloading = YES;
 83 }
 84 
 85 /**
 86  * 暂停下载
 87  */
 88 - (void)pause
 89 {
 90     [self.conn cancel];
 91     self.conn = nil;
 92     
 93     _downloading = NO;
 94 }
 95 
 96 #pragma mark - NSURLConnectionDataDelegate 代理方法
 97 /**
 98  *  1. 当接受到服务器的响应(连通了服务器)就会调用
 99  */
100 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
101 {
102 #warning 一定要判断
103     if (self.totalLength) return;
104     
105     // 1.创建一个空的文件到沙盒中
106     NSFileManager *mgr = [NSFileManager defaultManager];
107     // 刚创建完毕的大小是0字节
108     [mgr createFileAtPath:self.destPath contents:nil attributes:nil];
109     
110     // 2.创建写数据的文件句柄
111     self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];
112     
113     // 3.获得完整文件的长度
114     self.totalLength = response.expectedContentLength;
115 }
116 
117 /**
118  *  2. 当接受到服务器的数据就会调用(可能会被调用多次, 每次调用只会传递部分数据)
119  */
120 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
121 {
122     // 累加长度
123     self.currentLength += data.length;
124     
125     // 显示进度
126     double progress = (double)self.currentLength / self.totalLength;
127     if (self.progressHandler) { // 传递进度值给block
128         self.progressHandler(progress);
129     }
130     
131     // 移动到文件的尾部
132     [self.writeHandle seekToEndOfFile];
133     // 从当前移动的位置(文件尾部)开始写入数据
134     [self.writeHandle writeData:data];
135 }
136 
137 /**
138  *  3. 当服务器的数据接受完毕后就会调用
139  */
140 - (void)connectionDidFinishLoading:(NSURLConnection *)connection
141 {
142     // 清空属性值
143     self.currentLength = 0;
144     self.totalLength = 0;
145     
146     if (self.currentLength == self.totalLength) {
147         // 关闭连接(不再输入数据到文件中)
148         [self.writeHandle closeFile];
149         self.writeHandle = nil;
150     }
151     
152     if (self.completionHandler) {
153         self.completionHandler();
154     }
155 }
156 
157 /**
158  *  请求错误(失败)的时候调用(请求超时\断网\没有网, 一般指客户端错误)
159  */
160 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
161 {
162     if (self.failureHandler) {
163         self.failureHandler(error);
164     }
165 }
166 
167 @end

 

 1 #import "HMViewController.h"
 2 #import "HMFileDownloader.h"
 3 
 4 @interface HMViewController ()
 5 @property (weak, nonatomic) IBOutlet UIProgressView *progressView;
 6 @property (nonatomic, strong) HMFileDownloader *fileDownloader;
 7 
 8 - (IBAction)start:(UIButton *)button;
 9 @end
10 
11 @implementation HMViewController
12 
13 - (HMFileDownloader *)fileDownloader
14 {
15     if (!_fileDownloader) {
16         _fileDownloader = [[HMFileDownloader alloc] init];
17         // 需要下载的文件远程URL
18         _fileDownloader.url = @"http://192.168.1.200:8080/MJServer/resources/jre.zip";
19         // 文件保存到什么地方
20         NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
21         NSString *filepath = [caches stringByAppendingPathComponent:@"jre.zip"];
22         _fileDownloader.destPath = filepath;
23 //        typeof(10) a = 20; // int a = 20;
24         
25         __weak typeof(self) vc = self;
26         _fileDownloader.progressHandler = ^(double progress) {
27             vc.progressView.progress = progress;
28         };
29         
30         _fileDownloader.completionHandler = ^{
31             NSLog(@"------下载完毕");
32         };
33         
34         _fileDownloader.failureHandler = ^(NSError *error){
35         
36         };
37     }
38     return _fileDownloader;
39 }
40 
41 - (void)viewDidLoad
42 {
43     [super viewDidLoad];
44     
45 }
46 
47 // 按钮文字: "开始", "暂停"
48 - (IBAction)start:(UIButton *)button { // self.currentLength == 200
49     if (self.fileDownloader.isDownloading) { // 暂停下载
50         [self.fileDownloader pause];
51         
52         [button setTitle:@"恢复" forState:UIControlStateNormal];
53     } else { // 开始下载
54         [self.fileDownloader start];
55         
56         [button setTitle:@"暂停" forState:UIControlStateNormal];
57     }
58 }
59 
60 @end

 

posted @ 2016-01-25 18:51  xiaocaoera  阅读(226)  评论(0编辑  收藏  举报