iOS开发网络篇—多线程断点下载
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开发网络篇—多线程断点下载相关推荐
- iOS开发网络篇—使用ASI框架进行文件下载
iOS开发网络篇-使用ASI框架进行文件下载 说明:本文介绍iOS网络编程中经常用到的框架ASI,如何使用该框架进行文件的下载. 一.简单介绍 代码示例: 1 #import "YYView ...
- iOS开发网络篇—数据缓存
iOS开发网络篇-数据缓存 一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造成以 ...
- iOS开发网络篇—搭建本地服务器
iOS开发网络篇-搭建本地服务器 一.简单说明 说明:提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提示:提前准备好的软件 apache- ...
- 02.iOS开发网络篇—HTTP协议
iOS开发网络篇-HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...
- iOS开发网络篇—文件的上传
说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: Y ...
- IOS开发网络篇之──ASIHTTPRequest详解
目录 目录 发起一个同步请求 创建一个异步请求 队列请求 请求队列上下文 ASINetworkQueues, 它的delegate提供更为丰富的功能 取消异步请求 安全的内存回收建议 向服务器端上传数 ...
- iOS开发网络篇—NSURLConnection基本使用
一.NSURLConnection的常用类 (1)NSURL:请求地址 (2)NSURLRequest:封装一个请求,保存发给服务器的全部数据,包括一个NSURL对象,请求方法.请求头.请求体.... ...
- iOS开发网络篇—NSURLConnection基本使用(一)
一.NSURLConnection的常用类 (1)NSURL:请求地址 (2)NSURLRequest:封装一个请求,保存发给服务器的全部数据,包括一个NSURL对象,请求方法.请求头.请求体.. ...
- iOS开发网络篇—网络编程基础
一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过网络跟外界进行数据交互.数据更新 ...
最新文章
- ArcGIS对AutoCAD操作的图文教程
- 使用 Oracle GoldenGate 进行实时数据集成
- PPT 下载 | 桑文锋:数据化建设的时代机遇
- aapt2 生成资源 public flag 标记
- 2.5万美元奖金!滴滴算法工程师详解专业赛事:2021 SIGSPATIAL GISCUP
- 华为交换机同一vlan不同网段的通信
- 微服务网关Ocelot
- MySQL事务管理+安全管理+MySQL数据类型
- UI代码练习-视图的层次关系
- python身份证号掩盖出生日期的代码_利用Python制作全国身份证号验证及查询系统!就问你吊不吊!...
- php $rs1- gt eof,PHP_PHP速成大法,简单介绍一下PHP的语法
1、嵌 - phpStudy
- Elasticsearch实践(四):IK分词
- c语言编程我爱你红色代码,C语言告白代码,一闪一闪亮晶晶~
- 震撼!七大议题全数入选!九州云与您相约温哥华
- 2019上半年系统集成项目管理工程师真题与答案
- “瘦瘦”让健康管理流行起来
- 计算机如何默认一种打字法,如何设置输入法,教您如何设置电脑的默认输入法...
- 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (二)
- 杜骡的前端面试题(大全)
- 不平等博弈_不平等与全球性大流行:完美的风暴?
热门文章
- ajax如何请求json文件,简单的ajax请求加载外部json文件
- php数组合并如何不覆盖,php如何实现合并数组并且不覆盖重复值
- ntp服务器源码c语言,搭建自己的NTP时间服务器
- linux内核syscall_define6,Syscall系统调用Linux内核跟踪
- Spartan-6的MCB模块、GTP模块、PCIe端点模块
- 关于vmstat,top,ps aux查看的cpu占用率不一致的问题
- 从语句 char* p=test 说起
- linux实现机器之间的账号免密登陆
- 中间件(5)负载均衡
- Zoom Capability