ios 一个杂乱的多任务下载模版(单例模式,释放什么的还没有处理好,不过可以对您们的需求作相应修改)

.h文件

#import <Foundation/Foundation.h>
#import <FileProvider/FileProvider.h>
#define FileStorePath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:FileName]
#define TotalLengthPlist [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"DownTask.plist"]
#define DownloadLength [[[NSFileManager defaultManager] attributesOfItemAtPath:FileStorePath error:nil][NSFileSize] integerValue]

//typedef void (^successBlock) (NSString *fileStorePath);
//typedef void (^failBlock) (NSError*error);
//typedef void  (^progressBlock) (float progress);
@interface DownLoadFileManager : NSObject<NSURLSessionDataDelegate>
@property(copy,nonatomic)void (^successBlock)(NSString*fileStorePath,NSString*url) ;
@property(copy,nonatomic)void (^failBlock)(NSError *error,NSString*url) ;
@property(copy,nonatomic)void (^progressBlock)(float progress,NSString*url);

//本地下载列表
@property(nonatomic,strong)NSMutableArray *downLoadList;
//session数组
@property(nonatomic,strong)NSMutableArray <NSURLSession*> *sessionArr;
//sessionTask数组
@property(nonatomic,strong)NSMutableArray <NSURLSessionDataTask*>*sessionTaskArr;
@property(nonatomic,strong)NSMutableArray<NSOutputStream*>*outputStreamArr;
-(void)downloadWithUrl:(NSString *)url progress:(void (^)(float progress,NSString*url))progressBlock success:(void(^)(NSString *filePath,NSString*url))successBlock fail:(void(^)(NSError*error,NSString*url))failBlock;
-(void)stopTask;
+(instancetype)shareManager;
//添加下载任务,本地plist数组,增加一个元素,元素为字典,字典:name文件名,size文件总大小,finished是否下载完毕,url下载链接。
//
@end

.m文件

#import "DownLoadFileManager.h"

@implementation DownLoadFileManager
static id _instance;
//单例
+(instancetype)shareManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}
//检测本地下载列表是否有未完成的任务
-(NSMutableArray *)downLoadList{
    if (!_downLoadList) {
        _downLoadList = [NSMutableArray array];
        [_downLoadList arrayByAddingObjectsFromArray:[NSArray arrayWithContentsOfFile:TotalLengthPlist]];
    }
    return _downLoadList;
}
//开启所有未完成的下载任务
-(void)startAllTaskWithprogress:(void (^)(float progress,NSString*url))progressBlock success:(void (^)(NSString *filepath,NSString*url))successBlock fail:(void (^)(NSError *error,NSString*url))failBlock{
    self.successBlock = successBlock;
    self.failBlock = failBlock;
    self.progressBlock = progressBlock;
    for (int i = 0; i<self.downLoadList.count; i++) {
        NSMutableDictionary *dic = [NSMutableDictionary  dictionaryWithDictionary:self.downLoadList[i]];
        if ([dic[@"finished"] isEqualToString:@"0"]) {
            //获取到有未下载完成的任务时
            //生成新的task,task的url从本地存储的里边去取
            [self addATaskToArrWithUrl:dic[@"url"] name:dic[@"name"]];
        }
    }
    
}
-(void)addATaskToArrWithUrl:(NSString*)url name:(NSString*)name {
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init] ];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
    NSString *range = [NSString stringWithFormat:@"bytes=%ld-",[[[NSFileManager defaultManager] attributesOfItemAtPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:name] error:nil][NSFileSize] integerValue]];
    [request setValue:range forHTTPHeaderField:@"range"];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
    
    NSOutputStream*outStream = [NSOutputStream outputStreamToFileAtPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:name] append:YES];
    [self.outputStreamArr addObject:outStream];
    
    [task resume];
    
    [self.sessionArr addObject:session];
    [self.sessionTaskArr addObject:task];
    
}
//添加一个单个下载任务
-(void)downloadWithUrl:(NSString *)url progress:(void (^)(float progress,NSString*url))progressBlock success:(void(^)(NSString *filePath,NSString*url))successBlock fail:(void(^)(NSError*error,NSString*url))failBlock{
    self.successBlock = successBlock;
    self.failBlock = failBlock;
    self.progressBlock = progressBlock;
    
    
    NSMutableDictionary *newDownLoadTaskDic = [NSMutableDictionary dictionaryWithDictionary:@{@"name":[self getHashTypeStrWithUrl:url],@"url":url,@"size":@"0",@"finished":@"0"}];
    [self.downLoadList addObject:newDownLoadTaskDic];
    [self.downLoadList writeToFile:TotalLengthPlist atomically:YES];
    
    
    [self addATaskToArrWithUrl:url name:[self getHashTypeStrWithUrl:url]];
}
-(void)stopTask{
    //取出相应的task,并暂停
//    [self.task suspend];
}
-(NSMutableArray<NSOutputStream *> *)outputStreamArr{
    if (!_outputStreamArr) {
        _outputStreamArr = [[NSMutableArray alloc] init];
    }
    return _outputStreamArr;
}

-(NSMutableArray<NSURLSession *> *)sessionArr{
    if (!_sessionArr) {
        _sessionArr = [[NSMutableArray alloc] init];
    }
    return _sessionArr;
}
-(NSMutableArray<NSURLSessionDataTask *> *)sessionTaskArr{
    if (!_sessionTaskArr) {
        _sessionTaskArr = [[NSMutableArray alloc] init];
    }
    return _sessionTaskArr;
}

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    
    for (int i = 0; i<self.sessionArr.count; i++) {
        if (session==[self.sessionArr objectAtIndex:i]) {
            //output获取,然后开始书写
            [self.outputStreamArr[i] write:data.bytes maxLength:data.length];
            
            float progress =  1.0*([[[NSFileManager defaultManager] attributesOfItemAtPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",[self.downLoadList[i] objectForKey:@"name"] ]] error:nil][NSFileSize] integerValue])/[NSString stringWithFormat:@"%@",[self.downLoadList[i] objectForKey:@"size"] ].intValue;
            if (self.progressBlock) {
                self.progressBlock(progress, [NSString stringWithFormat:@"%@",[self.downLoadList[i] objectForKey:@"url"]]);
            }
        }
    }
    
}
-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
    completionHandler(NSURLSessionAuthChallengeUseCredential,[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
    
    NSString *url = response.URL.absoluteString;
    for (int i = 0; i<self.downLoadList.count; i++) {
        if ([url isEqualToString:[self.downLoadList[i] objectForKey:@"url"]]) {
            [self.outputStreamArr[i] open];
            
            NSInteger totallength = response.expectedContentLength+[[[NSFileManager defaultManager] attributesOfItemAtPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self.downLoadList[i] objectForKey:@"size"] ] error:nil][NSFileSize] integerValue];
            NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:self.downLoadList[i]];
            [dic setObject:[NSString  stringWithFormat:@"%ld",totallength] forKey:@"size"];
            [self.downLoadList replaceObjectAtIndex:i withObject:dic];
            [self.downLoadList writeToFile:TotalLengthPlist atomically:YES];
        }
    }
    completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    return;
    if (error) {
        if (self.failBlock) {
//            self.failBlock(error);
            self.successBlock = nil;
            self.progressBlock = nil;
            self.failBlock = nil;
        }
        //取出相应的写入流,task,并置空释放,或关闭
//        self.stream = nil;
//        self.task = nil;
    }else{
        if (self.successBlock) {
//            self.successBlock(FileStorePath);
            self.successBlock = nil;
            self.failBlock = nil;
            self.progressBlock = nil;
        }
        //取出相应的写入流,task,并置空释放,或关闭
//        [self.stream close];
//        self.stream = nil;
//        self.task = nil;
    }
}
-(NSString*)getHashStrWithUrl:(NSString*)url{
    return [NSString stringWithFormat:@"%lu",(unsigned long)[url hash]];
}
//hash.m4a,文件类型后缀名
-(NSString*)getHashTypeStrWithUrl:(NSString*)url{
    NSArray*strArr = [url componentsSeparatedByString:@"."];
    if (strArr.count>1) {
        url = [NSString stringWithFormat:@"%@.%@",[self getHashStrWithUrl:url],strArr[strArr.count-1]];
        return url;
    }else{
        return [self getHashStrWithUrl:url];
    }
    return [self getHashStrWithUrl:url];
}

@end

调用方法,开启一个下载任务:

(要开启几个下载任务,就使用添加几个downloadWithUrl方法,URL是你要下载的资源的远程地址):

- (IBAction)startDownload:(id)sender {
    NSString *url = @"http://audio.xmcdn.com/group11/M01/93/AF/wKgDa1dzzJLBL0gCAPUzeJqK84Y539.m4a";
    
    [[DownLoadFileManager shareManager] downloadWithUrl:url progress:^(float progress, NSString *url) {
        NSLog(@"progress: %f \n URL:%@",progress,url);
    } success:^(NSString *filePath, NSString *url) {
        NSLog(@"filepath: %@ \n URL:%@",filePath,url);
    } fail:^(NSError *error, NSString *url) {
        NSLog(@"error: %@ \n URL:%@",error.userInfo[NSLocalizedDescriptionKey],url);
    }];
    
    NSString *url1 = @"https://wqs.jd.com/promote/superfestival/superfestival.mp4";
    [[DownLoadFileManager shareManager] downloadWithUrl:url1 progress:^(float progress, NSString *url) {
        NSLog(@"progress: %f \n URL:%@",progress,url);
    } success:^(NSString *filePath, NSString *url) {
        NSLog(@"filepath: %@ \n URL:%@",filePath,url);
    } fail:^(NSError *error, NSString *url) {
        NSLog(@"error: %@ \n URL:%@",error.userInfo[NSLocalizedDescriptionKey],url);
    }];
    
}
- (IBAction)pauseDownload:(id)sender {
    [[DownLoadFileManager shareManager] stopTask];
    
}


更多问题,欢迎加群讨论:565191947

猜你喜欢

转载自blog.csdn.net/a787188834/article/details/80404553