#import <Foundation/Foundation.h>
@class XHDownLoadManager;
#pragma mark - delegate Method
@protocol XHDownLoadManagerDelegate <NSObject>
/** 下载失败*/
- (void)downLoadFailed:(XHDownLoadManager *)downLoadManager withError:(NSError *)error;
/** 下载进度:0.00%*/
- (void)downLoad:(XHDownLoadManager *)downLoadManager withProgress:(float)progress;
/** 下载完成进度:0/1*/
- (void)downLoadFinished:(XHDownLoadManager *)downLoadManager withFinishedCount:(NSInteger)finishedCount andTotalCount:(NSInteger)totalCount;
@end
#pragma mark - Object
@interface XHDownLoadManager : NSObject
/** documentName(要保存的文件夹的名字,不能为空)*/
@property (nonatomic, copy) NSString *documentName;
/** delegate*/
@property (nonatomic, weak) id<XHDownLoadManagerDelegate> delegate;
/** downLoadUrlStr*/
@property (nonatomic, copy) NSString *downLoadUrlStr;
/** downLoadUrlStrArray*/
@property (nonatomic, copy) NSArray *downLoadUrlStrArray;
/** 下载管理者*/
+ (instancetype)downLoadManager;
/** 下载文件*/
//单文件下载
- (void)downLoadFileWithUrlStr:(NSString *)urlStr;
//数组下载
- (void)downLoadFilesWithUrlStrArray:(NSArray *)urlStrArray;
/** 暂停下载*/
- (void)pauseDownLoad;
/** 取消下载*/
- (void)cancleDownLoad;
/** 恢复下载*/
- (void)resumeDownLoad;
@end
#import "XHDownLoadManager.h"
@interface XHDownLoadManager ()<NSURLSessionDelegate,NSURLSessionDownloadDelegate>
{
NSInteger _totalCount;//总任务数
NSInteger _finishedCount;//当前完成数
}
//单任务使用
/** session*/
@property (nonatomic,strong) NSURLSession *downLoadSession;
/** downLoadTask*/
@property (nonatomic,strong) NSURLSessionDownloadTask *downLoadTask;
/** resumeData*/
@property (nonatomic,copy) NSData *resumeData;
//多任务下载使用:暂不使用
/** downLoadTaskArray*/
@property (nonatomic,strong) NSMutableArray *downLoadTaskArray;
/** resumeDataArray*/
@property (nonatomic,strong) NSMutableArray *resumeDataArray;
@end
@implementation XHDownLoadManager
#pragma mark - LazyLoad
- (NSMutableArray *)resumeDataArray{
if (_resumeDataArray == nil) {
self.resumeDataArray = [NSMutableArray new];
}
return _resumeDataArray;
}
- (NSMutableArray *)downLoadTaskArray{
if (_downLoadTaskArray == nil) {
self.downLoadTaskArray = [NSMutableArray new];
}
return _downLoadTaskArray;
}
- (NSURLSession *)downLoadSession{
if (_downLoadSession == nil) {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
self.downLoadSession = session;
_downLoadSession = session;
}
return _downLoadSession;
}
/** 管理对象*/
+ (instancetype)downLoadManager{
return [[self alloc] init];
}
#pragma mark - custom Method
/** 暂停下载*/
- (void)pauseDownLoad{
__weak typeof (self) weakSelf = self;
/** 保存下载进度*/
[self.downLoadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
weakSelf.resumeData = resumeData;
weakSelf.downLoadTask = nil;
}];
}
/** 取消下载*/
- (void)cancleDownLoad{
if (self.downLoadSession) {
_finishedCount = 0;
[self.delegate downLoad:self withProgress:0];
[self.delegate downLoadFinished:self withFinishedCount:_finishedCount andTotalCount:_totalCount];
/** 清除本地存储*/
[self saveDownloadDataYesOrClearDownLoadDataNo:NO withLocalUrl:nil];
/** 取消下载*/
self.resumeData = nil;
[self.downLoadTask cancel];
self.downLoadTask = nil;
}
}
/** 恢复下载*/
- (void)resumeDownLoad{
if (self.resumeData) {//有缓存数据,即需要恢复下载
/** 从缓存处恢复下载*/
self.downLoadTask = [self.downLoadSession downloadTaskWithResumeData:self.resumeData];
/** 恢复下载*/
[self.downLoadTask resume];
/** 缓存置空*/
self.resumeData = nil;
}
}
/** 单个Url下载*/
- (void)downLoadFileWithUrlStr:(NSString *)urlStr{
self.downLoadUrlStr = urlStr;
}
/** 数组下载*/
- (void)downLoadFilesWithUrlStrArray:(NSArray *)urlStrArray{
self.downLoadUrlStrArray = urlStrArray;
}
#pragma mark - setter and getter
/** 单个地址下载*/
- (void)setDownLoadUrlStr:(NSString *)downLoadUrlStr{
/** 设置总下载个数*/
if (!_totalCount) {
_totalCount = 1;
[self.delegate downLoadFinished:self withFinishedCount:_finishedCount andTotalCount:_totalCount];
}
_downLoadUrlStr = downLoadUrlStr;
/** 判断是否当前地址已经下载,如果已下载直接开启下一个任务*/
NSString *fileStr = [downLoadUrlStr componentsSeparatedByString:@"#"].firstObject;
NSString *urlStr = [fileStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:urlStr];
NSURLSessionDownloadTask *downLoadTask = [self.downLoadSession downloadTaskWithURL:URL];
self.downLoadTask = downLoadTask;
[downLoadTask resume];
}
/** 数组下载*/
- (void)setDownLoadUrlStrArray:(NSArray *)downLoadUrlStrArray{
_downLoadUrlStrArray = downLoadUrlStrArray;
_totalCount = downLoadUrlStrArray.count;
/** 同时下载*/
/*
for (int i = 0; i < downLoadUrlStrArray.count; i ++) {
NSURL *URL = [NSURL URLWithString:URLPATH];
NSURLSessionDownloadTask *downLoadTask = [self.downLoadSession downloadTaskWithURL:URL];
[self.downLoadTaskArray addObject:downLoadTask];
[downLoadTask resume];
}
*/
/** 非同时下载*/
if (_totalCount) {
[self.delegate downLoadFinished:self withFinishedCount:_finishedCount andTotalCount:_totalCount];
[self downLoadFileWithUrlStr:[downLoadUrlStrArray firstObject]];
}
}
#pragma mark - delegate
/** 下载成功*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
//1.保存下载
[self saveDownloadDataYesOrClearDownLoadDataNo:YES withLocalUrl:location];
//2.开启另一个任务
[self startAnotherTask];
}
/** 下载完成、中断或失败调用*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (error) {//下载错误
if ([error.localizedDescription isEqualToString:@"cancelled"]) {
NSLog(@"用户取消/暂停下载");
}else{
/** 返回错误原因*/
[self.delegate downLoadFailed:self withError:error];
/** 开启另一个下载*/
[self startAnotherTask];
}
}
}
/** 下载进度: 0.00% */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
float currentRatio = totalBytesWritten * 1.0 / totalBytesExpectedToWrite;
[self.delegate downLoad:self withProgress:currentRatio];
}
#pragma mark - downLoad
/** 开启另一个下载*/
- (void)startAnotherTask{
_finishedCount ++;
/** 返回当前已下载(包括下载失败的)*/
[self.delegate downLoadFinished:self withFinishedCount:_finishedCount andTotalCount:_totalCount];
/** 开启另一个下载*/
if (_finishedCount < _totalCount) {
//开启另一个下载
[self downLoadFileWithUrlStr:self.downLoadUrlStrArray[_finishedCount]];
}else{
_finishedCount = 0;
NSLog(@"已完成所有下载!");
}
}
/** 保存或删除本地数据*/
- (void)saveDownloadDataYesOrClearDownLoadDataNo:(BOOL)isSaveData withLocalUrl:(NSURL *)location{
NSFileManager *fileManager = [NSFileManager defaultManager];//文件管理
//文件夹路径
NSString *documentPath = [NSString stringWithFormat:@"%@%@",[NSHomeDirectory() stringByAppendingString:@"/Documents/"],self.documentName];
/** 创建文件夹*/
if (![fileManager fileExistsAtPath:documentPath]) {
[fileManager createDirectoryAtPath:documentPath withIntermediateDirectories:YES attributes:nil error:nil];
}
//文件路径
NSString *filePath = [NSString stringWithFormat:@"%@/%ld.mp3",documentPath,_finishedCount];
//转换为地址
NSURL *fileUrl=[NSURL fileURLWithPath:filePath];
NSError *error;
BOOL succeed;
if (isSaveData) {
//移除原先
[fileManager removeItemAtURL:fileUrl error:nil];
//保存单个
succeed = [fileManager moveItemAtURL:location toURL:fileUrl error:&error];
if (succeed) {
NSLog(@"保存文件成功:%@",fileUrl);
}
else{
NSLog(@"保存文件失败:%@",error);
}
}else{
//删除所有
succeed = [fileManager removeItemAtPath:documentPath error:&error];
if (succeed) {
NSLog(@"删除文件夹成功:%@",documentPath);
}
else{
NSLog(@"删除文件夹失败:%@",error);
}
}
}
@end