ios NSURLSessionDataTask 封装下载 断点续传 不可以后台下载(一)

想了解使用NSURLSessionDownloadTask,进行封装下载的,请看这篇文章点击打开链接


使用:

 BackgroundDownloadTool_v2 *tool = [BackgroundDownloadTool_v2 new];
    tool.urlStr = @"http://baobab.wdjcdn.com/1455888619273255747085_x264.mp4";
    tool.fileName = @"jin.mp4";
    [tool downloadProgress:^(CGFloat progress) {
        self.label.text = [NSString stringWithFormat:@"%f",progress];
    } complement:^(NSString *path, NSError *err) {
        if (err) {
            
        }else {
            
        }
    }];
    [tool startOrContinueDownload];

主要代码:

BackgroundDownloadTool_v2.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface BackgroundDownloadTool_v2 : NSObject
@property(nonatomic,strong)NSString *identifier;//唯一SessionConfiguration
@property(nonatomic,strong)NSString *fileName;//保存的文件名
@property(nonatomic,strong)NSString *urlStr;
@property (nonatomic, copy) void (^backgroundSessionCompletionHandler)();

- (void)startOrContinueDownload;//开始或继续下载
- (void)pauseDownload;//暂停下载
- (void)cancelDownload;//取消下载
- (void)removeDownloadFile;//移除已下载好的文件

- (void)downloadProgress:(void (^)(CGFloat progress))downloadProgressBlock complement:(void (^)(NSString *path, NSError *err))completeBlock;

@end

BackgroundDownloadTool_v2.m

import "BackgroundDownloadTool_v2.h"

@interface BackgroundDownloadTool_v2 ()<NSURLSessionDataDelegate>
@property (nonatomic,strong) NSString *DownloadPath;
@property (nonatomic,strong) NSString *Location;
@property (nonatomic,strong) NSString *TotalDataLengthDictionaryPath;
@property (nonatomic,strong) NSFileManager *manage;
@property(nonatomic,strong)NSMutableDictionary *totalDataLengthDictionary;

@property(nonatomic,strong)NSURLSession *session;
@property(nonatomic,strong)NSURLSessionDataTask *dataTask;
@property(nonatomic,strong)NSOutputStream *stream;

@property(nonatomic,copy)void (^downloadProgressBlock)(CGFloat progress);
@property(nonatomic,copy)void (^completeBlock)(NSString *path, NSError *err);

@end
@implementation BackgroundDownloadTool_v2
- (NSFileManager *)manage{
    if (!_manage){
        _manage = [NSFileManager defaultManager];
    }
    return _manage;
}

-(NSString *)Location {
    if (!_Location) {
        _Location =[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"BackgroundDownload"];
        [self.manage createDirectoryAtPath:_Location withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return _Location;
}

- (NSString *)DownloadPath {
    if (!_DownloadPath) {
        _DownloadPath =[self.Location stringByAppendingPathComponent:self.fileName];
    }
    return _DownloadPath;
}

-(NSString *)TotalDataLengthDictionaryPath {
    if (!_TotalDataLengthDictionaryPath) {
        _TotalDataLengthDictionaryPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"totalDataLengththDictionaryPath.plist"];
    }
    return _TotalDataLengthDictionaryPath;
}

- (NSMutableDictionary *)totalDataLengthDictionary {
    if (!_totalDataLengthDictionary) {
        _totalDataLengthDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:self.TotalDataLengthDictionaryPath];
        if (!_totalDataLengthDictionary) {
            _totalDataLengthDictionary = [NSMutableDictionary dictionary];
        }
    }
    return _totalDataLengthDictionary;
}

- (NSOutputStream *)stream {
    if (!_stream) {
        _stream = [[NSOutputStream alloc]initToFileAtPath:self.DownloadPath append:YES];
    }
    return _stream;
}

- (NSURLSession *)session {
    if (!_session) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    }
    return _session;
}

- (NSURLSessionDataTask *)dataTask {
    if (!_dataTask) {
        NSError *error = nil;
        
        NSInteger alreadyDownloadLength = [self AlreadyDownloadLength];
        NSInteger totalDataLength = [self TotalDataLength];
        
        if (totalDataLength && totalDataLength == alreadyDownloadLength) {//说明已经下载完毕
            
            !self.downloadProgressBlock?:self.downloadProgressBlock(1);
            !self.completeBlock?:self.completeBlock(self.DownloadPath,error);
            return nil;
            
        }else if (totalDataLength < alreadyDownloadLength) {//如果已经存在的文件比目标大说明下载文件错误执行删除文件重新下载
        
            [[NSFileManager defaultManager]removeItemAtPath:self.DownloadPath error:&error];
            if (!error) {
                alreadyDownloadLength = 0;
            }else{
                NSLog(@"创建任务失败请重新开始");
                return nil;
            }
        }
        
        NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlStr]];
        
        //设置request的请求头
        //Range:bytes=xxx-xxx
        [mutableRequest setValue:[NSString stringWithFormat:@"bytes=%ld-",alreadyDownloadLength] forHTTPHeaderField:@"Range"];
        _dataTask = [self.session dataTaskWithRequest:mutableRequest];
    }
    return _dataTask;
}



- (void)downloadProgress:(void (^)(CGFloat progress))downloadProgressBlock complement:(void (^)(NSString *path, NSError *err))completeBlock {
    self.downloadProgressBlock = downloadProgressBlock;
    self.completeBlock = completeBlock;
}

- (void)startOrContinueDownload {
    [self.dataTask resume];
}

- (void)pauseDownload {
    [self.dataTask suspend];
}

- (void)cancelDownload {
    [self.dataTask suspend];
    [self.dataTask cancel];
    self.dataTask = nil;
}

- (void)removeDownloadFile {
    NSError *error;
    if ([self.manage fileExistsAtPath:self.DownloadPath ] ) {
        [self.manage removeItemAtPath:self.DownloadPath  error:&error];
        if (error) {
            NSLog(@"removeItem error %@",error);
        }else {
            self.stream = [[NSOutputStream alloc]initToFileAtPath:self.DownloadPath append:YES];
            [self cancelDownload];
            
            [self.totalDataLengthDictionary removeObjectForKey:self.fileName];
            [self.totalDataLengthDictionary writeToFile:self.TotalDataLengthDictionaryPath atomically:YES];
        }
    }
    
    

}

//已经下载的长度
-(NSInteger)AlreadyDownloadLength {
    return [[[NSFileManager defaultManager]attributesOfItemAtPath:self.DownloadPath error:nil][NSFileSize] integerValue];
}

//总的数据长度
-(NSInteger)TotalDataLength {
    return [self.totalDataLengthDictionary[self.fileName] integerValue];
}

//服务器响应以后调用的代理方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
    
    //获取文件的全部长度
    self.totalDataLengthDictionary[self.fileName] = @([response.allHeaderFields[@"Content-Length"] integerValue] + [self AlreadyDownloadLength]);
    [self.totalDataLengthDictionary writeToFile:self.TotalDataLengthDictionaryPath atomically:YES];
    
    [self.stream open];
    completionHandler(NSURLSessionResponseAllow);
}

//接收到数据后调用的代理方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    //把服务器传回的数据用stream写入沙盒中
    [self.stream write:data.bytes maxLength:data.length];
    
    CGFloat downloadProgress = 1.0 * [self AlreadyDownloadLength] / [self TotalDataLength];
    
    if (isnan(downloadProgress)) {
        downloadProgress = 0;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
       !self.downloadProgressBlock?:self.downloadProgressBlock(downloadProgress);
    });
    
}

//任务完成后调用的代理方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (error) {
        return;
    }
    [self.stream close];
    dispatch_async(dispatch_get_main_queue(), ^{
        !self.completeBlock?:self.completeBlock(self.DownloadPath,error);
    });
}

@end

我的业余技术微信公众号:YKJGZH,欢迎大家进入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值