iOS开发网络篇—多线程断点下载

说明:本文介绍多线程断点下载。项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件。因为实现过程较为复杂,所以下面贴出完整的代码。

实现思路:下载开始,创建一个和要下载的文件大小相同的文件(如果要下载的文件为100M,那么就在沙盒中创建一个100M的文件,然后计算每一段的下载量,开启多条线程下载各段的数据,分别写入对应的文件部分)。

项目中用到的主要类如下:

完成的实现代码如下:

主控制器中的代码:

 1 #import "YYViewController.h"2 #import "YYFileMultiDownloader.h"3 4 @interface YYViewController ()5 @property (nonatomic, strong) YYFileMultiDownloader *fileMultiDownloader;6 @end7 8 @implementation YYViewController9 -  (YYFileMultiDownloader *)fileMultiDownloader
10 {
11     if (!_fileMultiDownloader) {
12         _fileMultiDownloader = [[YYFileMultiDownloader alloc] init];
13         // 需要下载的文件远程URL
14         _fileMultiDownloader.url = @"http://192.168.1.200:8080/MJServer/resources/jre.zip";
15         // 文件保存到什么地方
16         NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
17         NSString *filepath = [caches stringByAppendingPathComponent:@"jre.zip"];
18         _fileMultiDownloader.destPath = filepath;
19     }
20     return _fileMultiDownloader;
21 }
22
23 - (void)viewDidLoad
24 {
25     [super viewDidLoad];
26
27 }
28
29 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
30 {
31     [self.fileMultiDownloader start];
32 }
33
34 @end

自定义一个基类

YYFileDownloader.h文件

 1 #import <Foundation/Foundation.h>2 3 @interface YYFileDownloader : NSObject4 {5     BOOL _downloading;6 }7 /**8  * 所需要下载文件的远程URL(连接服务器的路径)9  */
10 @property (nonatomic, copy) NSString *url;
11 /**
12  * 文件的存储路径(文件下载到什么地方)
13  */
14 @property (nonatomic, copy) NSString *destPath;
15
16 /**
17  * 是否正在下载(有没有在下载, 只有下载器内部才知道)
18  */
19 @property (nonatomic, readonly, getter = isDownloading) BOOL downloading;
20
21 /**
22  * 用来监听下载进度
23  */
24 @property (nonatomic, copy) void (^progressHandler)(double progress);
25
26 /**
27  * 开始(恢复)下载
28  */
29 - (void)start;
30
31 /**
32  * 暂停下载
33  */
34 - (void)pause;
35 @end

YYFileDownloader.m文件

1 #import "YYFileDownloader.h"
2
3 @implementation YYFileDownloader
4 @end

下载器类继承自YYFileDownloader这个类

YYFileSingDownloader.h文件

 1 #import "YYFileDownloader.h"2 3 @interface YYFileSingleDownloader : YYFileDownloader4 /**5  *  开始的位置6  */7 @property (nonatomic, assign) long long begin;8 /**9  *  结束的位置
10  */
11 @property (nonatomic, assign) long long end;
12 @end

YYFileSingDownloader.m文件

  1 #import "YYFileSingleDownloader.h"2 @interface YYFileSingleDownloader() <NSURLConnectionDataDelegate>3 /**4  * 连接对象5  */6 @property (nonatomic, strong) NSURLConnection *conn;7 8 /**9  *  写数据的文件句柄10  */11 @property (nonatomic, strong) NSFileHandle *writeHandle;12 /**13  *  当前已下载数据的长度14  */15 @property (nonatomic, assign) long long currentLength;16 @end17 18 @implementation YYFileSingleDownloader19 20 - (NSFileHandle *)writeHandle21 {22     if (!_writeHandle) {23         _writeHandle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];24     }25     return _writeHandle;26 }27 28 /**29  * 开始(恢复)下载30  */31 - (void)start32 {33     NSURL *url = [NSURL URLWithString:self.url];34     // 默认就是GET请求35     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];36     // 设置请求头信息37     NSString *value = [NSString stringWithFormat:@"bytes=%lld-%lld", self.begin + self.currentLength, self.end];38     [request setValue:value forHTTPHeaderField:@"Range"];39     self.conn = [NSURLConnection connectionWithRequest:request delegate:self];40     41     _downloading = YES;42 }43 44 /**45  * 暂停下载46  */47 - (void)pause48 {49     [self.conn cancel];50     self.conn = nil;51     52     _downloading = NO;53 }54 55 56 #pragma mark - NSURLConnectionDataDelegate 代理方法57 /**58  *  1. 当接受到服务器的响应(连通了服务器)就会调用59  */60 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response61 {62     63 }64 65 /**66  *  2. 当接受到服务器的数据就会调用(可能会被调用多次, 每次调用只会传递部分数据)67  */68 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data69 {70     // 移动到文件的尾部71     [self.writeHandle seekToFileOffset:self.begin + self.currentLength];72     // 从当前移动的位置(文件尾部)开始写入数据73     [self.writeHandle writeData:data];74     75     // 累加长度76     self.currentLength += data.length;77     78     // 打印下载进度79     double progress = (double)self.currentLength / (self.end - self.begin);80     if (self.progressHandler) {81         self.progressHandler(progress);82     }83 }84 85 /**86  *  3. 当服务器的数据接受完毕后就会调用87  */88 - (void)connectionDidFinishLoading:(NSURLConnection *)connection89 {90     // 清空属性值91     self.currentLength = 0;92     93     // 关闭连接(不再输入数据到文件中)94     [self.writeHandle closeFile];95     self.writeHandle = nil;96 }97 98 /**99  *  请求错误(失败)的时候调用(请求超时\断网\没有网, 一般指客户端错误)
100  */
101 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
102 {
103
104 }
105
106 @end

设计多线程下载器(利用HMFileMultiDownloader能开启多个线程同时下载一个文件)

一个多线程下载器只下载一个文件

YYFileMultiDownloader.h文件

1 #import "YYFileDownloader.h"
2
3 @interface YYFileMultiDownloader : YYFileDownloader
4
5 @end

YYFileMultiDownloader.m文件

 1 #import "YYFileMultiDownloader.h"2 #import "YYFileSingleDownloader.h"3 4 #define YYMaxDownloadCount 45 6 @interface YYFileMultiDownloader()7 @property (nonatomic, strong) NSMutableArray *singleDownloaders;8 @property (nonatomic, assign) long long totalLength;9 @end
10
11 @implementation YYFileMultiDownloader
12
13 - (void)getFilesize
14 {
15     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.url]];
16     request.HTTPMethod = @"HEAD";
17
18     NSURLResponse *response = nil;
19 #warning 这里要用异步请求
20     [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
21     self.totalLength = response.expectedContentLength;
22 }
23
24 - (NSMutableArray *)singleDownloaders
25 {
26     if (!_singleDownloaders) {
27         _singleDownloaders = [NSMutableArray array];
28
29         // 获得文件大小
30         [self getFilesize];
31
32         // 每条路径的下载量
33         long long size = 0;
34         if (self.totalLength % YYMaxDownloadCount == 0) {
35             size = self.totalLength / YYMaxDownloadCount;
36         } else {
37             size = self.totalLength / YYMaxDownloadCount + 1;
38         }
39
40         // 创建N个下载器
41         for (int i = 0; i<YYMaxDownloadCount; i++) {
42             YYFileSingleDownloader *singleDownloader = [[YYFileSingleDownloader alloc] init];
43             singleDownloader.url = self.url;
44             singleDownloader.destPath = self.destPath;
45             singleDownloader.begin = i * size;
46             singleDownloader.end = singleDownloader.begin + size - 1;
47             singleDownloader.progressHandler = ^(double progress){
48                 NSLog(@"%d --- %f", i, progress);
49             };
50             [_singleDownloaders addObject:singleDownloader];
51         }
52
53         // 创建一个跟服务器文件等大小的临时文件
54         [[NSFileManager defaultManager] createFileAtPath:self.destPath contents:nil attributes:nil];
55
56         // 让self.destPath文件的长度是self.totalLengt
57         NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];
58         [handle truncateFileAtOffset:self.totalLength];
59     }
60     return _singleDownloaders;
61 }
62
63 /**
64  * 开始(恢复)下载
65  */
66 - (void)start
67 {
68     [self.singleDownloaders makeObjectsPerformSelector:@selector(start)];
69
70     _downloading = YES;
71 }
72
73 /**
74  * 暂停下载
75  */
76 - (void)pause
77 {
78     [self.singleDownloaders makeObjectsPerformSelector:@selector(pause)];
79     _downloading = NO;
80 }
81
82 @end

补充说明:如何获得将要下载的文件的大小?

转载于:https://www.cnblogs.com/187n/p/5060909.html

iOS开发网络篇—多线程断点下载相关推荐

  1. iOS开发网络篇—使用ASI框架进行文件下载

    iOS开发网络篇-使用ASI框架进行文件下载 说明:本文介绍iOS网络编程中经常用到的框架ASI,如何使用该框架进行文件的下载. 一.简单介绍 代码示例: 1 #import "YYView ...

  2. iOS开发网络篇—数据缓存

    iOS开发网络篇-数据缓存 一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造成以 ...

  3. iOS开发网络篇—搭建本地服务器

    iOS开发网络篇-搭建本地服务器 一.简单说明 说明:提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提示:提前准备好的软件 apache- ...

  4. 02.iOS开发网络篇—HTTP协议

    iOS开发网络篇-HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...

  5. iOS开发网络篇—文件的上传

    说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: Y ...

  6. IOS开发网络篇之──ASIHTTPRequest详解

    目录 目录 发起一个同步请求 创建一个异步请求 队列请求 请求队列上下文 ASINetworkQueues, 它的delegate提供更为丰富的功能 取消异步请求 安全的内存回收建议 向服务器端上传数 ...

  7. iOS开发网络篇—NSURLConnection基本使用

    一.NSURLConnection的常用类 (1)NSURL:请求地址 (2)NSURLRequest:封装一个请求,保存发给服务器的全部数据,包括一个NSURL对象,请求方法.请求头.请求体.... ...

  8. iOS开发网络篇—NSURLConnection基本使用(一)

      一.NSURLConnection的常用类 (1)NSURL:请求地址 (2)NSURLRequest:封装一个请求,保存发给服务器的全部数据,包括一个NSURL对象,请求方法.请求头.请求体.. ...

  9. iOS开发网络篇—网络编程基础

    一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过网络跟外界进行数据交互.数据更新 ...

最新文章

  1. ArcGIS对AutoCAD操作的图文教程
  2. 使用 Oracle GoldenGate 进行实时数据集成
  3. PPT 下载 | 桑文锋:数据化建设的时代机遇
  4. aapt2 生成资源 public flag 标记
  5. 2.5万美元奖金!滴滴算法工程师详解专业赛事:2021 SIGSPATIAL GISCUP
  6. 华为交换机同一vlan不同网段的通信
  7. 微服务网关Ocelot
  8. MySQL事务管理+安全管理+MySQL数据类型
  9. UI代码练习-视图的层次关系
  10. python身份证号掩盖出生日期的代码_利用Python制作全国身份证号验证及查询系统!就问你吊不吊!...
  11. php $rs1- gt eof,PHP_PHP速成大法,简单介绍一下PHP的语法 1、嵌 - phpStudy
  12. Elasticsearch实践(四):IK分词
  13. c语言编程我爱你红色代码,C语言告白代码,一闪一闪亮晶晶~
  14. 震撼!七大议题全数入选!九州云与您相约温哥华
  15. 2019上半年系统集成项目管理工程师真题与答案
  16. “瘦瘦”让健康管理流行起来
  17. 计算机如何默认一种打字法,如何设置输入法,教您如何设置电脑的默认输入法...
  18. 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (二)
  19. 杜骡的前端面试题(大全)
  20. 不平等博弈_不平等与全球性大流行:完美的风暴?

热门文章

  1. ajax如何请求json文件,简单的ajax请求加载外部json文件
  2. php数组合并如何不覆盖,php如何实现合并数组并且不覆盖重复值
  3. ntp服务器源码c语言,搭建自己的NTP时间服务器
  4. linux内核syscall_define6,Syscall系统调用Linux内核跟踪
  5. Spartan-6的MCB模块、GTP模块、PCIe端点模块
  6. 关于vmstat,top,ps aux查看的cpu占用率不一致的问题
  7. 从语句 char* p=test 说起
  8. linux实现机器之间的账号免密登陆
  9. 中间件(5)负载均衡
  10. Zoom Capability