IOS开发中一般会用到数据下载操作,下载的内容分为小文件和大文件下载方式又分为异步跟同步。
一 小文件
上面无论是A还是B方式进行大的数据下载操作都非常不好,A跟B首先它都会在主线程内进行下载操作,等到数据下载完毕它才会继续让程序往下执行。而且也无法监视下载进度,影响用户体验,还有一个弊端就是下载的数据都会一个劲的往data这个变量里面塞而它又是存放在内存中的,如果你的URL路径资源是50MB那么你的程序占用的内存将随着这个data迅速猛增,内存资源将会非常危险也很致命,所以开发中绝对不会采取这种方式,它只能适合小的数据下载。
二 :大文件
实现过程: 创建四个关联对象
<span style="font-size:14px;color:#CC0000;">NSURLSessionConfiguration 配合 Session</span>
<span style="font-size:14px;color:#CC0000;">NSURLSession 任务类</span>
<span style="font-size:14px;color:#CC0000;">NSFileManager 文件管理类</span>
<span style="font-size:14px;color:#CC0000;">NSURLSessionDataTask 任务类型
</span>
<span style="font-size:14px;color:#CC0000;">NSURLSessionDataDelegate 实现代理的两个方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data</span>
<span style="font-size:14px;color:#CC0000;">- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error</span>
<span style="font-size:14px;color:#CC0000;"> #import "ViewController.h"
#import "DACircularProgressView.h"
@interface ViewController ()<NSURLSessionDataDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *pictureView;
/**
* 管理session
*/
@property (nonatomic,strong)NSURLSessionConfiguration* configuration;
/**
* 任务
*/
@property (nonatomic,strong)NSURLSession* session;
/**
* 图片数据
*/
@property (nonatomic,strong)NSMutableData* data;
/**
* 图片URL资源
*/
@property (nonatomic,strong)NSMutableArray* allPicture;
/**
* 文件管理
*/
@property (nonatomic,strong)NSFileManager* manager;
/**
* 下标
*/
@property (nonatomic,assign)NSInteger index;
/**
* 下载进度
*/
@property (weak, nonatomic)DACircularProgressView *downProgress;
@end
@implementation ViewController
- (NSFileManager *)manager
{
if (!_manager)
{
_manager = [NSFileManager defaultManager];
}
return _manager;
}
- (NSMutableArray *)allPicture
{
if (!_allPicture)
{
_allPicture = [NSMutableArray array];
}
return _allPicture;
}
/**
* 懒加载
*/
- (NSURLSession*)session
{
if (!_session)
{
_configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:_configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
/**
* 沙盒路径
*/
- (NSString*)returnTheFilePatch:(NSString*)url
{
NSString* last = url.lastPathComponent;
NSString* patch = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
return [patch stringByAppendingPathComponent:last];
}
#pragma makr 监听下载进度
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
// 主线程刷新
dispatch_async(dispatch_get_main_queue(), ^{
// 获取url路径
NSString* result = self.allPicture[self.index];
// 拼接返回路径
NSString* patch = [self returnTheFilePatch:result];
// 创建文件句柄
NSFileHandle* filehandle = [NSFileHandle fileHandleForWritingAtPath:patch];
[filehandle seekToEndOfFile];
// 继续写入数据
[filehandle writeData:data];
// 关闭句柄
[filehandle closeFile];
// 显示到控件
self.pictureView.image = [UIImage imageWithContentsOfFile:patch];
// 进度条
self.downProgress.progress = dataTask.countOfBytesReceived*1.0/dataTask.countOfBytesExpectedToReceive;
});
}
#pragma mark 下载完毕
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
// url下标
++self.index;
// 下载
[self downLoadImageUrl:self.allPicture[self.index]];
// 清空原有图片数据
self.data = nil;
}
/**
* 大文件下载
*/
- (IBAction)bigFileDown:(id)sender {
// 拼接URL图片路径
for (int m=5; m<=70; m++)
{
NSString* patch =[NSString stringWithFormat:@"http://t1.niutuku.com/960/59/59-1427%02d.jpg",m];
[self.allPicture addObject:patch];
}
// 执行下载
[self downLoadImageUrl:self.allPicture[0]];
}
/**
* 下载
*/
- (void)downLoadImageUrl:(NSString*)patch
{
// 返回拼接路径
NSString* filePatch = [self returnTheFilePatch:patch];
// 创建空文件
[self.manager createFileAtPath:filePatch contents:nil attributes:nil];
// url资源
NSURL* URL = [NSURL URLWithString:patch];
// 创建任务
NSURLSessionDataTask* dataTastk = [self.session dataTaskWithURL:URL];
// 执行
[dataTastk resume];
}
- (void)viewDidLoad {
// 创建进度条View
DACircularProgressView* dacircul = [[DACircularProgressView alloc] init];
self.downProgress = dacircul;
dacircul.trackTintColor = [UIColor blackColor];
dacircul.frame = CGRectMake(130, 200, 60, 60);
[self.view addSubview:dacircul];
self.index = 0;
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}</span>
效果:
三 :断点续传
实现过程:
更改任务类型:
<span style="font-size:14px;color:#CC0000;"></span><pre name="code" class="objc"><span style="font-size:14px;color:#CC0000;">NSURLSessionDownloadTask</span>
添加协议
<span style="font-size:14px;color:#CC0000;">NSURLSessionDownloadDelegate
</span>
增加一个 NSdata变量用于记录下载进度
<span style="font-size:14px;color:#CC0000;">@property (nonatomic,strong)NSData* data;</span>
实现两个协议 (下载完毕)(正在下载)
<span style="font-size:14px;color:#CC0000;">- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
</span>
增加三个方法
<span style="font-size:14px;color:#CC0000;">start(开始) pause(暂停) 恢复(recover)</span>
代码:
<span style="font-size:14px;color:#FF0000;">@interface myView ()<NSURLSessionDownloadDelegate>
/**
* 图片URL资源
*/
@property (nonatomic,strong)NSMutableArray* allPicture;
/**
* 图片View
*/
@property (weak, nonatomic) IBOutlet UIImageView *pictureView;
/**
* 下载任务
*/
@property (nonatomic,strong)NSURLSessionDownloadTask* task;
/**
* 执行
*/
@property (nonatomic,strong)NSURLSession* session;
/**
* 断点数据
*/
@property (nonatomic,strong)NSData* data;
/**
* 进度
*/
@property (nonatomic,strong)HiProgressView* downPlan;
/**
* 下载按钮
*/
@property (weak, nonatomic) IBOutlet UIButton *downBtn;
/**
* 图片下标
*/
@property (nonatomic,assign)NSInteger index;
@end
@implementation myView
- (NSMutableArray *)allPicture
{
if (!_allPicture)
{
_allPicture = [NSMutableArray array];
}
return _allPicture;
}
- (NSURLSession *)session
{
if (!_session)
{
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
/**
* 开始
*/
- (void)start
{
[self.downBtn setTitle:@"暂停" forState:UIControlStateNormal];
// 取出url路径
NSString* patch = self.allPicture[self.index];
// 开始下载
[self downLoadImageUrl:patch];
}
/**
* 暂停
*/
- (void)pause
{
[self.downBtn setTitle:@"开始" forState:UIControlStateNormal];
//防止无法释放
__weak typeof(self)View = self;
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
// 保存数据
View.data = resumeData;
// 删除任务
self.task = nil;
}];
}
/**
* 恢复
*/
- (void)recover
{
[self.downBtn setTitle:@"暂停" forState:UIControlStateNormal];
// 传入上次数据
self.task = [self.session downloadTaskWithResumeData:self.data];
// 继续执行
[self.task resume];
// 清空
self.data = nil;
}
#pragma mark 下载
- (IBAction)downPicture:(id)sender
{
if (self.task == nil)
{
if (self.data == nil)
{
[self start];
}else
{
[self recover];
}
}else
{
[self pause];
}
}
/**
* 下载
*/
- (void)downLoadImageUrl:(NSString*)patch
{
// 图片下标
++self.index;
// url资源
NSURL* URL = [NSURL URLWithString:patch];
// 创建任务
self.task = [self.session downloadTaskWithURL:URL];
// 执行
[self.task resume];
}
#pragma mark 下载完毕执行
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
// 拿到沙盒文件夹路径
NSString* caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
// 路径拼接
NSString* patch = [caches stringByAppendingPathComponent:location.lastPathComponent];
// 移动文件夹
NSFileManager* fileManage = [NSFileManager defaultManager];
[fileManage moveItemAtPath:location.path toPath:patch error:nil];
// 显示到数据
dispatch_async(dispatch_get_main_queue(), ^{
self.pictureView.image = [UIImage imageWithContentsOfFile:patch];
// 继续下载
NSString* urlPatch = self.allPicture[self.index];
[self downLoadImageUrl:urlPatch];
});
}
#pragma mark 监听进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
self.downPlan.progress = totalBytesWritten*1.0 / totalBytesExpectedToWrite;
}
/**
* 沙盒路径
*/
- (NSString*)returnTheFilePatch:(NSString*)url
{
NSString* last = url.lastPathComponent;
NSString* patch = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
return [patch stringByAppendingPathComponent:last];
}
- (void)viewDidLoad {
self.index = 0;
// 拼接URL图片路径
for (int m=5; m<=70; m++)
{
NSString* patch =[NSString stringWithFormat:@"http://t1.niutuku.com/960/59/59-1427%02d.jpg",m];
[self.allPicture addObject:patch];
}
// 下载进度
CGRect rect = CGRectMake(0, 150, 320, 10);
HiProgressView *progressView = [[HiProgressView alloc]initWithFrame:rect withProgress:0];//传入参数范围0~1
[self.view addSubview:progressView];
self.downPlan = progressView;
[super viewDidLoad];
}</span>
效果图