参考资源地址:http://www.jianshu.com/p/5e6630e999fa
我们需要遵守NSURLSessionDownloadDelegate协议,并且对协议中的方法进行实现。
当使用NSURLSessionDownloadTask的时候,我们就可以不用设置请求头,因为系统给封装了两个方法,使我们可以更简单的进行断点续传。
- 一个是任务暂停时候的的带有block回调函数的方法,方法中有个NSData类型的参数resumeData是用于记录下载的URL地址和已下载的总共的字节数两部分,而不是直接存储的已下载的数据.我们需要做的就是把resumeData保存下来,用于后面的断点续传.
- (void)cancelByProducingResumeData:(void (^)(NSData * __nullable resumeData))completionHandler;
- 另外一个就是NSURLSession 自带的使用resumeData创建NSURLSessionDownloadTask的初始化方法.我们只要把上面的resumeData的传过来创建就可以了。
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
直接上马
\#import "ViewController.h"
@interface ViewController ()<NSURLSessionDataDelegate>
@property (strong, nonatomic) IBOutlet UIImageView *imageView;//图片
@property (strong, nonatomic) IBOutlet UIButton *breakpointButton;
@property (strong, nonatomic) IBOutlet UILabel *progressLabel;
@property(nonatomic,strong)NSString *filePaths;//文件的沙盒路径
@property(nonatomic,assign)NSInteger fileSize;//本地已经下载的文件的大小
@property(nonatomic,assign)NSInteger altogetherSize;//文件总共的大小
@property (nonatomic, strong) NSURLSessionDownloadTask *task;
@property (nonatomic, strong) NSData *resumeData;
@property (nonatomic, strong) NSURLSession *session;
@end
@implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;//图片大小自适应
self.filePaths = 0;
self.fileSize = 0;
self.altogetherSize = 0;
}
//pragma mark --- 断点下载 ---
-(IBAction)breakpointData:(UIButton *)sender {
if (self.task == nil) { // 开始(继续)下载
if (self.resumeData) { // 恢复
[sender setTitle:@"暂停" forState:UIControlStateNormal];
[self resume];
} else { // 开始
[self start];
[sender setTitle:@"暂停" forState:UIControlStateNormal];
}
} else { // 暂停
[sender setTitle:@"继续" forState:UIControlStateNormal];
[self pause];
}
}
//懒加载
-(NSURLSession *)session
{
if (!_session) {
// 获得session
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
-(void)start
{
// 1.创建一个下载任务
NSURL *url = [NSURL URLWithString:@"http://www.deskcar.com/desktop/fengjing/20125700336/18.jpg"];
self.task = [self.session downloadTaskWithURL:url];
// 2.开始任务
[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;
}];
}
//NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
//根据请求头中的文件名在沙盒中直接创建路径
NSURLResponse *response = downloadTask.response;
NSString *filePaths =[self cacheDir:response.suggestedFilename];
self.filePaths = filePaths;
NSFileManager *fileManager = [NSFileManager defaultManager];
//将临时的下载文件(在内存中)放入沙盒中.
[fileManager moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePaths] error:nil];
self.imageView.image = [UIImage imageWithContentsOfFile:self.filePaths];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
if (totalBytesExpectedToWrite > self.altogetherSize) {
self.altogetherSize = totalBytesExpectedToWrite;
NSLog(@"%ld",(long)self.altogetherSize);
}
NSLog(@"%f",(double)totalBytesWritten / self.altogetherSize);
self.progressLabel.text = [NSString stringWithFormat:@"%.0f %",(double)100*totalBytesWritten / self.altogetherSize];
if ((double)totalBytesWritten / self.altogetherSize == 1) {
//关掉用户交互
[self.breakpointButton setTitle:@"完成" forState:UIControlStateNormal];
self.breakpointButton.userInteractionEnabled = NO;
}
}
//输入一个字符串,则在沙盒中生成路径
// 传入字符串,直接在沙盒Cache中生成路径
- (NSString *)cacheDir:(NSString *)paths
{
NSString *cache = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
return [cache stringByAppendingPathComponent:[paths lastPathComponent]];
}
@end