想了解使用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,欢迎大家进入