iOS开发-大文件下载与断点下载思路
- 大文件下载
方案一:利用NSURLConnection和它的代理方法,及NSFileHandle(iOS9后不建议使用)
相关变量:@property (nonatomic,strong) NSFileHandle *writeHandle;
@property (nonatomic,assign) long long totalLength;1>发送请求
// 创建一个请求
NSURL *url = [NSURL URLWithString:@""];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 使用NSURLConnection发起一个异步请求
[NSURLConnection connectionWithRequest:request delegate:self];2>在代理方法中处理服务器返回的数据
/** 在接收到服务器的响应时调用下面这个代理方法
1.创建一个空文件
2.用一个句柄对象关联这个空文件,目的是方便在空文件后面写入数据
*/
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response
{
// 创建文件路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
NSString *filePath = [caches stringByAppendingPathComponent:@"videos.zip"]; // 创建一个空的文件到沙盒中
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr createFileAtPath:filePath contents:nil attributes:nil]; // 创建一个用来写数据的文件句柄
self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filePath]; // 获得文件的总大小
self.totalLength = response.expectedContentLength;
} /** 在接收到服务器返回的文件数据时调用下面这个代理方法
利用句柄对象往文件的最后面追加数据
*/
- (void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data
{
// 移动到文件的最后面
[self.writeHandle seekToEndOfFile]; // 将数据写入沙盒
[self.writeHandle writeData:data];
} /**
在所有数据接收完毕时,关闭句柄对象
*/
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 关闭文件并清空
[self.writeHandle closeFile];
self.writeHandle = nil;
}方案二:使用NSURLSession的NSURLSessionDownloadTask和NSFileManager
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@""];
// 可以用来下载大文件,数据将会存在沙盒里的tmp文件夹
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// location :临时文件存放的路径(下载好的文件) // 创建存储文件路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
// response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:response.suggestedFilename]; /**将临时文件剪切或者复制到Caches文件夹
AtPath :剪切前的文件路径
toPath :剪切后的文件路径
*/
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr moveItemAtPath:location.path toPath:file error:nil];
}];
[task resume];方案三:使用NSURLSessionDownloadDelegate的代理方法和NSFileManger
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 创建一个下载任务并设置代理
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURL *url = [NSURL URLWithString:@""];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
[task resume];
} #pragma mark -
/**
下载完毕后调用
参数:lication 临时文件的路径(下载好的文件)
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
// 创建存储文件路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
// response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename]; /**将临时文件剪切或者复制到Caches文件夹
AtPath :剪切前的文件路径
toPath :剪切后的文件路径
*/
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr moveItemAtPath:location.path toPath:file error:nil];
} /**
每当下载完一部分时就会调用(可能会被调用多次)
参数:
bytesWritten 这次调用下载了多少
totalBytesWritten 累计写了多少长度到沙盒中了
totalBytesExpectedToWrite 文件总大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
// 这里可以做些显示进度等操作
} /**
恢复下载时使用
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
// 用于断点续传
} - 断点下载
方案一:
1>在方案一的基础上新增两个变量和按扭@property (nonatomic,assign) long long currentLength;
@property (nonatomic,strong) NSURLConnection *conn;2>在接收到服务器返回数据的代理方法中添加如下代码
// 记录断点,累计文件长度
self.currentLength += data.length;3>点击按钮开始(继续)或暂停下载
- (IBAction)download:(UIButton *)sender { sender.selected = !sender.isSelected; if (sender.selected) { // 继续(开始)下载
NSURL *url = [NSURL URLWithString:@""];
// ****关键点是使用NSMutableURLRequest,设置请求头Range
NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url]; NSString *range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
[mRequest setValue:range forHTTPHeaderField:@"Range"]; // 下载
self.conn = [NSURLConnection connectionWithRequest:mRequest delegate:self];
}else{
[self.conn cancel];
self.conn = nil;
}
}4>在接受到服务器响应执行的代理方法中第一行添加下面代码,防止重复创建空文件
if (self.currentLength) return;
方案二:使用NSURLSessionDownloadDelegate的代理方法
所需变量@property (nonatomic,strong) NSURLSession *session;
@property (nonatomic,strong) NSData *resumeData; //包含了继续下载的开始位置和下载的url
@property (nonatomic,strong) NSURLSessionDownloadTask *task;方法
// 懒加载session
- (NSURLSession *)session
{
if (!_session) {
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
} - (IBAction)download:(UIButton *)sender { sender.selected = !sender.isSelected;
if (self.task == nil) { // 开始(继续)下载
if (self.resumeData) { // 原先有数据则恢复
[self resume];
}else{
[self start]; // 原先没有数据则开始
}
}else{ // 暂停
[self pause];
}
} // 从零开始
- (void)start{
NSURL *url = [NSURL URLWithString:@""];
self.task = [self.session downloadTaskWithURL:url];
[self.task resume];
} // 暂停
- (void)pause{
__weak typeof(self) vc = self;
[self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//resumeData : 包含了继续下载的开始位置和下载的url
vc.resumeData = resumeData;
vc.task = nil;
}];
} // 恢复
- (void)resume{
// 传入上次暂停下载返回的数据,就可以回复下载
self.task = [self.session downloadTaskWithResumeData:self.resumeData];
// 开始任务
[self.task resume];
// 清空
self.resumeData = nil;
} #pragma mark - NSURLSessionDownloadDelegate
/**
下载完毕后调用
参数:lication 临时文件的路径(下载好的文件)
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
// 创建存储文件路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
// response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename]; /**将临时文件剪切或者复制到Caches文件夹
AtPath :剪切前的文件路径
toPath :剪切后的文件路径
*/
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr moveItemAtPath:location.path toPath:file error:nil];
} /**
每当下载完一部分时就会调用(可能会被调用多次)
参数:
bytesWritten 这次调用下载了多少
totalBytesWritten 累计写了多少长度到沙盒中了
totalBytesExpectedToWrite 文件总大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
// 这里可以做些显示进度等操作
} /**
恢复下载时使用
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
iOS开发-大文件下载与断点下载思路的更多相关文章
- iOS开发网络篇—多线程断点下载
iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...
- iOS开发网络篇之文件下载、大文件下载、断点下载
from: http://www.jianshu.com/p/f65e32012f07
- iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充
一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...
- iOS开发系列-文件下载
小文件下载 NSURLConnection下载小文件 #import "ViewController.h" @interface ViewController ()<NSUR ...
- 使用NSURLSessionDownloadTask实现大文件下载-监听下载进度
- 5.1 涉及知识点(1)创建NSURLSession并设置代理,通过NSURLSessionDownloadTask并以代理的方式来完成大文件的下载 //1.创建NSURLSession,设置代理 ...
- iOS开发大神必备的Xcode插件
写在前面 工欲善其事,必先利其器,iOS开发中不仅要学会Xcode的基本操作,而且还得学会一些Xcode的使用技巧,如掌握常用的快捷键等,还有就是今天要说到的Xcode插件,下面我就为大家介绍几款开发 ...
- ios开发之网络数据的下载与上传
要实现网络数据的下载与上传,主要有三种方式 > NSURLConnection 针对少量数据,使用“GET”或“POST”方法从服务器获取数据,使用“POST”方法向服务器传输数据; > ...
- 【iOS】Resumable Doanloads(断点下载)
这里我们只讨论iOS平台下的通用app,我们可以自己写代码来实现resume downloads,解释如下. resume一个HTTP下载不难,但必须要理解一些关键的HTTP概念: entity ta ...
- 使用NSURLSessionDataTask实现大文件离线断点下载(完整)
6.1 涉及知识点(1)关于NSOutputStream的使用 //1. 创建一个输入流,数据追加到文件的屁股上 //把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建 NSOutputSt ...
随机推荐
- 版本控制工具Vault v7.0更新内容曝光【慧都独家】
SourceGear公司原定于2013年第三季度发布Vault 7.0版本.近日SourceGear就新版本的更新内容就行了发布,相信Vault 7.0版本也会于不久后面世. 那么Vault 7.0版 ...
- 【工作笔记五】html5的placeholder属性(IE如何兼容placeholder属性)
placeholder属性,IE对其的支持表示无奈,firefox.google chrome表示毫无压力. HTML5对Web Form做了许多增强,比如input新增的type类型.Form Va ...
- 安装系统提示选中的磁盘具有MBR分区表
引用:http://jingyan.baidu.com/article/ff42efa9693e88c19e22020c.html 进入bios看到 UEFI状态时 Enabled 启用状态,那么 ...
- 数据结构二叉树的java实现,包括二叉树的创建、搜索、删除和遍历
根据自己的学习体会并参考了一些网上的资料,以java写出了二叉树的创建.搜索.删除和遍历等操作,尚未实现的功能有:根据先序和中序遍历,得到后序遍历以及根据后序和中序遍历,得到先序遍历,以及获取栈的深度 ...
- 【分享】史上最全的Python电子书教程资源下载
网上搜集的,点击即可下载,希望提供给有需要的人^_^ O'Reilly.Python.And.XML.pdf 2.02 MB OReilly - Programming Python 2nd. ...
- 一个Shift的后门程序,可以让你可以进入你不知道密码的电脑
1.前提 你可以在平时亲身接触状态电脑,哪怕是在电脑主人不在的时候(虽然主人不在,或者关机了,进入电脑是要密码的). 2.原理 利用电脑连续按5次Shift会触发粘滞键,它会运行c:\winows\s ...
- Django解决 'ascii' codec can't encode characters in position
问题: 文件上传可以上传英文,无法上传中文的. 解决方法:对Apache进行配置 在/etc/apache2/envvars文件加上: export LANG='en_US.UTF-8'export ...
- 线程池python
原创博文,转载请注明出处 今天在学习python进程与线程时,无意间发现了线程池threadpool模块,见官方文档. 模块使用非常简单,前提是得需要熟悉线程池的工作原理. 我们知道系统处理任务时,需 ...
- CLR 的执行模型(2)
第一章 CLR 的执行模型(2) 本篇内容大纲 Framework 类库(Framework Class Library , FCL) 通用类型系统(Common Type System,CTS) 公 ...
- 初探performance.timing API
初探performance.timing API 浏览器新提供的performance接口精确的告诉我们当访问一个网站页面时当前网页每个处理阶段的精确时间(timestamp),以方便我们进行前端 ...