最近项目中遇到一个需求:在视频下载的时候能够暂停保存,能够显示下载进度,在下次进入界面的时候后能够继续下载,要求显示已下载的百分比;列表内能同时下载多个视频文件。思路如下:
1、在执行下载任务时,获取本次下载文件大小,下载一部分的同时写入到本地文件中,动态显示下载进度。
2、暂停下载。
3、继续下载任务,获取本地已下载文件大小。获取继续下载的任务的文件大小。
#import "DownloadHandle.h"
@interface DownloadHandle ()
@property (nonatomic , copy) NSString * downloadCompletePath;//下载完成路径
@property (nonatomic , strong) NSOutputStream * outputStream;//输出流;
@property (nonatomic , assign) NSInteger currentLength;//当前下载的长度
@property (nonatomic , assign) NSInteger totalLength;//全部下载长度
@property (nonatomic , copy)void(^completeFn)(NSError * error);
@property (nonatomic , copy)void(^recieveFn)(CGFloat progress);
@end
@implementation DownloadHandle
-(void)dealloc
{
[self.dataTask suspend];
self.dataTask = nil;
[self.outputStream close];
self.outputStream = nil;
}
/**
初始化函数
@param url 下载地址
@param filePath 文件名
@param recieveFn 接受到数据的回调
@param completeFn 下载完成后的回调
@return 实例对象
*/
-(instancetype)initWithUrl:(NSString *)url
filePath:(NSString *)filePath
recieveFn:(void(^)(CGFloat progress))recieveFn
completeFn:(void(^)(NSError *error))completeFn
{
if(self = [super init])
{
_url = url;
self.downloadCompletePath = filePath;
self.completeFn = completeFn;
self.recieveFn = recieveFn;
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSInteger currentDataSize = [self getCurrentDataSize];
NSString * range = [NSString stringWithFormat:@"bytes=%zd-",currentDataSize];
if(currentDataSize != 0)
_currentLength = currentDataSize;
request.timeoutInterval = 0;
[request setValue:range forHTTPHeaderField:@"Range"];
self.dataTask = [self.session dataTaskWithRequest:request];
[self.dataTask resume];
}
return self;
}
/**
暂停下载
*/
-(void)pauseDownload
{
[self.dataTask suspend];
}
/**
继续下载
@param recieveFn 继续下载以后的回调
@param completeFn 下载完成的回调
*/
-(void)continueDownloadWithRecieveFn:(void(^)(CGFloat progress))recieveFn
completeFn:(void(^)(NSError *error))completeFn
{
_recieveFn = recieveFn;
_completeFn = completeFn;
if(self.dataTask )
{
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_url]];
NSInteger currentDataSize = [self getCurrentDataSize];
NSString * range = [NSString stringWithFormat:@"bytes=%zd-",currentDataSize];
if(currentDataSize != 0)
_currentLength = currentDataSize;
request.timeoutInterval = 0;
[request setValue:range forHTTPHeaderField:@"Range"];
self.dataTask = [self.session dataTaskWithRequest:request];
[self.dataTask resume];
}
}
/**
停止下载
*/
-(void)stopDownload
{
[self.dataTask suspend];
self.dataTask = nil;
[self.outputStream close];
self.outputStream = nil;
}
/**
获取当前已下载的长度
@return 已下载的长度
*/
-(NSInteger)getCurrentDataSize
{
NSFileManager * manager = [NSFileManager defaultManager];
NSDictionary * dict = [manager attributesOfItemAtPath:self.downloadCompletePath error:nil];
NSInteger size = [dict[@"NSFileSize"] integerValue];
self.currentLength = size;
return size;
}
/**
获取当前下载进度百分比
@return 下载进度
*/
-(CGFloat)getCurrentProgress
{
CGFloat progress = [self getCurrentDataSize] * 1.0 /self.totalLength;
return progress;
}
#pragma mark ----------- NSURLSessionDownloadDelegate ----------
//
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSHTTPURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
NSLog(@"接收到服务器的响应");
NSLog(@"预期长度:%lld",response.expectedContentLength);
self.totalLength = response.expectedContentLength + _currentLength;;
//创建写入流
NSURL * path = [NSURL fileURLWithPath:self.downloadCompletePath];
NSOutputStream * stream = [NSOutputStream outputStreamWithURL:path append:YES];
[stream open];
self.outputStream = stream;
completionHandler(NSURLSessionResponseAllow);
}
//接受到数据后的回调 会多次回调
-(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveData:(nonnull NSData *)data
{
self.currentLength += data.length;
NSInteger downloadLength = [self.outputStream write:data.bytes maxLength:data.length];
CGFloat progress = 1.0 *self.currentLength / self.totalLength * 100;
NSLog(@"下载了百分比---->%f %% 下载文件大小%ld,文件总大小:%ld,本地写入的文件大小:%ld", progress,self.currentLength,self.totalLength,downloadLength);
self.recieveFn(progress);
}
//下载完成
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
[self.outputStream close];
self.outputStream = nil;
self.completeFn(error);
}
#pragma mark -------------------------懒加载--------------------------------
-(NSURLSession *)session
{
if(!_session)
{
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
@end