NSURLSession断点下载

#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

 

转载于:https://www.cnblogs.com/MrXHong/p/5673450.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值