ios的下载我们可以使用的方法有:NSData、NSURLConnection、NSURLSession还有第三方框架AFNetworking和ASI

  利用NSData方法和NSURLConnection的异步方法仅适合下载较小的文件,因为NSData是把数据一口气下载,下载大文件那么手机的内存会一下子暴涨,大文件下载可以用NSURLConnection代理方法、NSURLSession代理方法、AFNetworking和ASI:

  NSData:

// 在沙盒中得存储路径
NSString *str = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [str stringByAppendingPathComponent:@"test.exe"]; NSLog(@"%@",str); // 下载地址
NSURL *url = [NSURL URLWithString:@"http://68.duote.com.cn/fcengw.exe"]; NSData *data = [NSData dataWithContentsOfURL:url]; // 数据写入到沙盒
[data writeToFile:path atomically:YES];

  NSURLConnection异步方法:

// 在沙盒中得存储路径
NSString *str = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [str stringByAppendingPathComponent:@"test.exe"]; NSLog(@"%@",str); // 下载地址
NSURL *url = [NSURL URLWithString:@"http://68.duote.com.cn/fcengw.exe"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 异步方法
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { // 数据写入沙盒
[data writeToFile:path atomically:YES];
}];

  利用NSURLConnection的代理方法来实现下载(NSURLConnectionDataDelegate):

  这其中使用了响应头expectedContentLength来获取文件的总大小,利用了请求头的键“Range”来设置暂停后下一次开始时的位置,利用了NSFileManager和NSFileHandle来设置分段存储下载的数据:

#pragma mark - 属性
// 文件句柄对象
@property (nonatomic,strong) NSFileHandle *fileHandle; // 文件总长度
@property (nonatomic,assign) long long contentLength; // 当前文件长度
@property (nonatomic,assign) long long currentLen; @property (nonatomic,strong) NSURLConnection *conn; #pragma mark - 点击事件
// 按钮点击事件
- (IBAction)startAndStop { // 设置按钮选中与否
_btn.selected = !_btn.selected; // 实现断点续传
if (_btn.selected){ // 按钮选中 // 下载地址
NSString *str = @"http://51.duote.org/haozip_duote.exe"; NSURL *url = [NSURL URLWithString:str]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // 设置请求头数据
NSString *range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLen];
[request setValue:range forHTTPHeaderField:@"Range"]; self.conn = [NSURLConnection connectionWithRequest:request delegate:self]; }else{ // 取消下载(暂停)
[self.conn cancel];
self.conn = nil;
}
} #pragma mark - NSURLConnectionDataDelegate代理
// 出错
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{ NSLog(@"出错 - %@",error.localizedDescription);
} // 接收到响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (self.currentLen) return; NSString *cacheStr = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [cacheStr stringByAppendingPathComponent:@"test.exe"]; // 创建一个空的文件
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr createFileAtPath:path contents:nil attributes:nil];

  // 句柄对象实例化
self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:path]; // 文件总大小(响应头取得)
NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
self.contentLength = resp.expectedContentLength; } // 接收数据
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 找到文件的末尾
[self.fileHandle seekToEndOfFile]; // 在末尾写入数据
[self.fileHandle writeData:data]; // 当前已下载长度
self.currentLen += data.length; // 下载百分比:当前已下载大小 / 文件总大小
self.progressView.progress = (double)self.currentLen / self.contentLength; NSLog(@"%f",self.progressView.progress); } // 接收完成
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"接收完成"); // 关闭
[self.fileHandle closeFile];
self.fileHandle = nil; self.currentLen = ;
self.contentLength = ; }

  利用NSURLSession的代理方法:

  NSURLSession是ios7后才有的方法,苹果官方旨在替代NSURLConnection

  NSURLSessionDataTask:解决一般的GET\POST的请求方法

  NSURLSessionDownloadTask:解决文件下载

  NSURLSessionUploadTask:文件上传

  A、NSURLSessionDataTask的操作:

// 下载地址
NSURL *url = [NSURL URLWithString:@"http://68.duote.com.cn/fcengw.exe"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // 这里进行json或XML解析
}]; // 3.开始任务
[task resume];

  B、NSURLSessionDownloadTask:不能看到下载进度

// session对象
NSURLSession *session = [NSURLSession sharedSession]; // 下载地址
NSString *str = @"http://51.duote.org/haozip_duote.exe"; // 创建一个下载task
NSURL *url = [NSURL URLWithString:str];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { ////// 因为任务下载是存在沙盒的temp文件中,并且下载完成后会被立即清除,所以这里将下载的文件剪切到caches中 // location : 临时文件的路径(下载好的文件) NSString *cacheStr = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// response.suggestedFilename : 建议使用的文件名,一般跟服务器端的文件名一致
NSString *path = [cacheStr stringByAppendingPathComponent:response.suggestedFilename]; // 将临时文件剪切或者复制Caches文件夹
NSFileManager *mgr = [NSFileManager defaultManager]; // AtPath : 剪切前的文件路径
// ToPath : 剪切后的文件路径
[mgr moveItemAtPath:location.path toPath:path error:nil];
}]; // 开始任务
[task resume];

  C:NSURLSessionDownloadDelegate的实现:

NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];

// session对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]; // 下载task
NSURL *url = [NSURL URLWithString:@"http://51.duote.org/haozip_duote.exe"];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url]; // 这里不要用block,如果用了block,那么方法会优先调用block,而不是代理方法
// 开始任务
[task resume]; #pragma mark - NSURLSessionDownloadDelegate代理
// 下载完毕后调用
- (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文件夹
NSFileManager *mgr = [NSFileManager defaultManager]; // AtPath : 剪切前的文件路径
// ToPath : 剪切后的文件路径
[mgr moveItemAtPath:location.path toPath:file error:nil];
} // 恢复下载时调用 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{ } // 每当下载一部分就会调用,可能会被调用多次
// bytesWritten 这次下载了多少
// totalBytesWritten 当前总共下载了多少到沙盒
// totalBytesExpectedToWrite 文件的总大小
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
double progress = (double)totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"下载进度---%f", progress);
}

  D、NSURLSession实现断点续传

// .m文件
@property (nonatomic, strong) NSURLSessionDownloadTask *task;
@property (nonatomic, strong) NSData *resumeData;
@property (nonatomic, strong) NSURLSession *session; - (NSURLSession *)session
{
if (!_session) {
// 获得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:@"http://xxx.com/mmg/cc.exe"];
self.task = [self.session downloadTaskWithURL:url]; // 开始任务
[self.task resume];
} // 恢复下载
- (void)resume
{
// 传入上次暂停下载返回的数据,就可以恢复下载
self.task = [self.session downloadTaskWithResumeData:self.resumeData]; // 开始任务
[self.task resume]; // 清空
self.resumeData = nil;
} // 暂停下载
- (void)pause
{
__weak typeof(self) vc = self;
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
// resumeData : 包含了继续下载的开始位置\下载的url
vc.resumeData = resumeData;
vc.task = nil;
}];
} #pragma mark - NSURLSessionDownloadDelegate 下载代理方法
- (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文件夹
NSFileManager *mgr = [NSFileManager defaultManager]; // AtPath : 剪切前的文件路径
// ToPath : 剪切后的文件路径
[mgr moveItemAtPath:location.path toPath:file error:nil];
} - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSLog(@"获得下载进度--%@", [NSThread currentThread]);
// 获得下载进度
self.progressView.progress = (double)totalBytesWritten / totalBytesExpectedToWrite;
} - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{ }

iOS 文件下载及断点续传的更多相关文章

  1. 【转】iOS 文件下载及断点续传

    ios的下载我们可以使用的方法有:NSData.NSURLConnection.NSURLSession还有第三方框架AFNetworking和ASI 利用NSData方法和NSURLConnecti ...

  2. iOS开发之网络编程--4、NSURLSessionDataTask实现文件下载(离线断点续传下载) <进度值显示优化>

    前言:根据前篇<iOS开发之网络编程--2.NSURLSessionDownloadTask文件下载>或者<iOS开发之网络编程--3.NSURLSessionDataTask实现文 ...

  3. 【SFTP】使用Jsch实现Sftp文件下载-支持断点续传和进程监控

    参考上篇文章: <[SFTP]使用Jsch实现Sftp文件下载-支持断点续传和进程监控>:http://www.cnblogs.com/ssslinppp/p/6248763.html  ...

  4. iOS开发之网络编程--3、NSURLSessionDataTask实现文件下载(离线断点续传下载)

    前言:使用NSURLSessionDownloadTask满足不这个需要离线断点续传的下载需求,所以这里就需要使用NSURLSessionDataTask的代理方法来处理下载大文件,并且实现离线断点续 ...

  5. iOS 文件下载

    iOS 视频音乐类等应用会用到“文件下载”.文件下载在iOS中的实现如下: 1.小文件下载 @interface ViewController () <NSURLConnectionDataDe ...

  6. 李洪强iOS开发之断点续传1

    未完待续.. // //  ViewController.m //  A18 - duo wen jian shang chuan // //  Created by 李洪强 on 16/6/29. ...

  7. C# 文件下载之断点续传

    注意,本文所说的断点续传特指 HTTP 协议中的断点续传.本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo. 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息.我 ...

  8. Winform文件下载之断点续传

    在本系列的前两篇文章中,分别向大家介绍了用于完成下载任务的 WebClinet 和 WinINet 的基本用法和一些实用技巧. 今天来为大家讲述下载过程中最常遇到的断点续传问题. 首先明确一点,本文所 ...

  9. iOS 文件下载和打开

    最近的项目要用到一个在线报告的下载,于是完成后自己在理一下思路,大体的实现了我要得需求. 话不多说,直接上代码 首先,取到网络文件的链接,进行判段是否需求再次下载还是直接打开 #pragma mark ...

随机推荐

  1. centos install redis

    1. 下载 [logan@localhost java]$ wget http://download.redis.io/releases/redis-3.2.8.tar.gz2. 解压    [log ...

  2. css模仿百度首页

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. webpack 启动 vue

    右击 package.json  单击show npm Scripts

  4. CCF201412-1 门禁系统

    试题编号: 201412-1 试题名称: 门禁系统 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况.每位读者有一个 ...

  5. python 案例一(电话铺)

    经过自己努力,做了一个简单的电话铺的录入和查询小程序,比较简单,喜欢的朋友可以练练手. 题目: 创建你自己的命令行 地址簿 程序.在这个程序中,你可以添加.修改.删除和搜索你的联系人(朋友.家人和同事 ...

  6. Python学习---同步条件event/队列queue1223

    写在前面: 在使用这些共享API的时候,我们要注意以下几点: 在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie).所以,有必要对每个Proce ...

  7. Oracle日常性能查看

    判断回滚段竞争的SQL语句:(当Ratio大于2时存在回滚段竞争,需要增加更多的回滚段)select rn.name, rs.GETS, rs.WAITS, (rs.WAITS / rs.GETS) ...

  8. python .loc vs .iloc区别

    1.loc意义:通过行标签索引行数据 例: loc[n]表示索引的是第n行(index 是整数) loc[‘d’]表示索引的是第’d’行(index 是字符) 2. .iloc   :通过行号获取行数 ...

  9. 全文检索及ElasticSearch框架学习

    1.   全文检索的通用步骤: 1.建库步骤: a 分词 b 倒排索引   :  关键词和记录Id的对应关系,1对多. 2.查询步骤: a 分词 b 查索引 c 取交集或并集 2.    产品使用全文 ...

  10. TFS--解决新创建的windows用户无法访问TFS的问题

    今天入职新同事,帮忙配置TFS的账号碰到一个问题,TFS账号是映射取administrators组得 所以新建用户之后,无法马上引入TFS.查询原因是 Builtin组中没有该账号,以前也总是碰到新加 ...