iOS开发网络篇—大文件的多线程断点下载(转)
iOS开发网络篇—多线程断点下载
说明:本文介绍多线程断点下载。项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件。因为实现过程较为复杂,所以下面贴出完整的代码。
实现思路:下载开始,创建一个和要下载的文件大小相同的文件(如果要下载的文件为100M,那么就在沙盒中创建一个100M的文件,然后计算每一段的下载量,开启多条线程下载各段的数据,分别写入对应的文件部分)。
项目中用到的主要类如下:
完成的实现代码如下:
主控制器中的代码:

- 1 #import "YYViewController.h"
- 2 #import "YYFileMultiDownloader.h"
- 3
- 4 @interface YYViewController ()
- 5 @property (nonatomic, strong) YYFileMultiDownloader *fileMultiDownloader;
- 6 @end
- 7
- 8 @implementation YYViewController
- 9 - (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 : NSObject
- 4 {
- 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 : YYFileDownloader
- 4 /**
- 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 @end
- 17
- 18 @implementation YYFileSingleDownloader
- 19
- 20 - (NSFileHandle *)writeHandle
- 21 {
- 22 if (!_writeHandle) {
- 23 _writeHandle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];
- 24 }
- 25 return _writeHandle;
- 26 }
- 27
- 28 /**
- 29 * 开始(恢复)下载
- 30 */
- 31 - (void)start
- 32 {
- 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)pause
- 48 {
- 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 *)response
- 61 {
- 62
- 63 }
- 64
- 65 /**
- 66 * 2. 当接受到服务器的数据就会调用(可能会被调用多次, 每次调用只会传递部分数据)
- 67 */
- 68 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- 69 {
- 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 *)connection
- 89 {
- 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 4
- 5
- 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

补充说明:如何获得将要下载的文件的大小?
iOS开发网络篇—大文件的多线程断点下载(转)的更多相关文章
- iOS开发网络篇—大文件的多线程断点下载
http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时 ...
- iOS开发网络请求——大文件的多线程断点下载
iOS开发中网络请求技术已经是移动app必备技术,而网络中文件传输就是其中重点了.网络文件传输对移动客户端而言主要分为文件的上传和下载.作为开发者从技术角度会将文件分为小文件和大文件.小文件因为文件大 ...
- ios开发网络学习十一:NSURLSessionDataTask离线断点下载(断点续传)
#import "ViewController.h" #define FileName @"121212.mp4" @interface ViewControl ...
- iOS开发网络篇-JSON文件的解析
一.什么是JSON数据 1.JSON的简单介绍 JSON:是一种轻量级的传输数据的格式,用于数据的交互 JSON是javascript语言的一个子集.javascript是个脚本语言(不需要编译),用 ...
- iOS开发网络篇—多线程断点下载
iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...
- iOS开发网络篇—文件的上传
iOS开发网络篇—文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代 ...
- iOS开发网络篇—简单介绍ASI框架的使用
iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大 ...
- iOS开发网络篇—HTTP协议
iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...
- iOS开发网络篇—使用ASI框架进行文件下载
iOS开发网络篇—使用ASI框架进行文件下载 说明:本文介绍iOS网络编程中经常用到的框架ASI,如何使用该框架进行文件的下载. 一.简单介绍 代码示例: #import "YYViewCo ...
随机推荐
- 用pf透明地将流量从一台机器转到另一台机器上的缘起及实现方式对比
下面是也是我在12580工作时发生的事情,重新记录并发出来.这种特殊需求很考 验PF的功底.在新旧系统并存,做重构的时候有时很需要这种救急的作法.一.缘起miscweb1(172.16.88.228) ...
- JAVA备忘录
本文主要是记录一下JAVA: 1.Arrays.的几个用法: fill:数组全部置一个数 sort:排序 binarySearch:二分查找 2.Map的用法: Map<Integer,Inte ...
- Sharepoint 2013 系列篇(安装部署)--上篇
前言 sharepoint的部署是按照物理拓扑图的架构来部署,按照物理拓扑图架构分为一层拓扑图架构,二层拓扑图架构,三层拓扑图架构,多层拓扑图架构. 按照分层的拓扑图部署是按照需求来划分的,一层拓扑图 ...
- Java中的堆和栈的区别
当一个人开始学习Java或者其他编程语言的时候,会接触到堆和栈,由于一开始没有明确清晰的说明解释,很多人会产生很多疑问,什么是堆,什么是栈,堆和栈有什么区别?更糟糕的是,Java中存在栈这样一个后进先 ...
- ubuntn14.04 32位安装hadoop2.7.2
1. 创建用户一枚, sudo addgroup hadoop sudo adduser -ingroup hadoop hadoop_lcc 2. 为新创建的用户添加sudo权限 sudo gedi ...
- 自定义View(二)ViewPage广告轮播
自定义View的第二个学习案例,使用ViewPage实现广告轮播,通过组合现有的View实现效果如下: 有关ViewPage使用可以学习谷歌官方API,和训练案例: 1.使用ViewPage实现屏幕滑 ...
- Part 2 How are the URL's mapped to Controller Action Methods?
Part 2 How are the URL's mapped to Controller Action Methods? The answer is ASP.NET Routing.Notice t ...
- 关于近期需要学习sqlserver2008
在胜利油田物探院借了一本书叫做 sqlserver2008宝典 第二版,但是看不下去 下面打算直接安装数据库上手了,边练边学
- 15条JavaScript最佳实践很经典噢
感觉比较经典,特转载腾讯大讲堂.本文档整理大部分公认的.或者少有争议的JavaScript良好书写规范(Best Practice).一些显而易见的常识就不再论述(比如要用对象支持识别判断,而不是浏览 ...
- vpn连接成功后,本地无法连接外网
把在远程网络上使用默认网关前面的对勾取消掉,确定就ok啦...