断点离线下载
- 以下代码只是提供一种思路,具体开发中还是需要自己去封装
- 存储文件总长度的方式还需要改进
// 需要下载的文件的URL
#define YWFileURL @"下载地址"
// 文件名(沙盒中的文件名,下载地址的MD5的字符串)
#define YWFileName YWFileURL.md5String
#define YWFileFullPath [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:YWFileName]
// 存储文件总长度的文件路径
#define YWTotalLengthFullPath [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"totalLength.plist"]
// 文件已下载的长度
#define YWDownloadLength [[[NSFileManager defaultManager] attributesOfItemAtPath:YWFileFullPath error:nil][NSFileSize] integerValue]
#import "ZLViewController.h"
#import "NSString+Hash.h"
@interface ZLViewController ()<NSURLSessionDataDelegate>
/**
下载任务
*/
@property(nonatomic, strong) NSURLSessionDataTask *task;
/**
NSURLSession
*/
@property(nonatomic, strong) NSURLSession *session;
/**
写文件的流对象
*/
@property(nonatomic, strong) NSOutputStream *stream;
/**
文件的总长度
*/
@property(nonatomic, assign) NSInteger totalLength;
@end
@implementation ZLViewController
- (NSURLSession *)session
{
if(_session == nil){
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
}
return _session;
}
- (NSOutputStream *)stream
{
if(_stream == nil){
_stream = [NSOutputStream outputStreamToFileAtPath:YWFileFullPath append:YES];
}
return _stream;
}
- (NSURLSessionDataTask *)task
{
if(_task == nil){
NSInteger totalLength = [[NSDictionary dictionaryWithContentsOfFile:YWTotalLengthFullPath][YWFileName] integerValue];
if(totalLength && YWDownloadLength == totalLength){
// 文件已经下载过了
return nil;
}
// 创建请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:YWFileURL]];
// 设置请求头
NSString *range = [NSString stringWithFormat:@"bytes=%zd-", YWDownloadLength];
[request setValue:range forHTTPHeaderField:@"Range"];
// 创建一个Data任务
_task = [self.session dataTaskWithRequest:request];
}
return _task;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",YWFileFullPath);
}
/**
开始下载
*/
- (IBAction)start:(id)sender {
// 启动任务
[self.task resume];
}
/**
暂停下载
*/
- (IBAction)pause:(id)sender {
[self.task suspend];
}
#pragma mark - NSURLSessionDataDelegate
/**
接收到响应
*/
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
// 打开流
[self.stream open];
// 获得服务器这次请求,返回数据的总长度
self.totalLength = [response.allHeaderFields[@"Content-Length"] integerValue] + YWDownloadLength;
// 存储总长度
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:YWTotalLengthFullPath];
if(dict == nil){
dict = [NSMutableDictionary dictionary];
}
dict[YWFileName] = @(self.totalLength);
[dict writeToFile:YWTotalLengthFullPath atomically:YES];
// 接收这个请求,允许接收服务器数据
completionHandler(NSURLSessionResponseAllow);
}
/**
接收到服务器返回的数据(这个方法可能被调用多次)
*/
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
// 写入数据
[self.stream write:data.bytes maxLength:data.length];
// 下载进度
NSLog(@"%f", 1.0 * YWDownloadLength / self.totalLength);
}
/**
请求完毕
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
[self.stream close];
self.stream = nil;
self.task = nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end