? ? ? ?最近項目中遇到一個需求:在視頻下載的時候能夠暫停保存统抬,能夠顯示下載進度匪蝙,在下次進入界面的時候后能夠繼續(xù)下載窟感,要求顯示已下載的百分比;列表內能同時下載多個視頻文件鲤嫡。思路如下:
????????1送挑、在執(zhí)行下載任務時,獲取本次下載文件大小暖眼,下載一部分的同時寫入到本地文件中惕耕,動態(tài)顯示下載進度。
? ? ? ? 2诫肠、暫停下載司澎。
? ? ? ? 3、繼續(xù)下載任務区赵,獲取本地已下載文件大小惭缰。獲取繼續(xù)下載的任務的文件大小。 ?
?#import "DownloadHandle.h"
@interface? DownloadHandle ()
@property (nonatomic , copy) NSString? *? downloadCompletePath;//下載完成路徑
@property (nonatomic , strong) NSOutputStream * outputStream;//輸出流笼才;
@property (nonatomic , assign) NSInteger currentLength;//當前下載的長度
@property (nonatomic , assign) NSInteger totalLength;//全部下載長度
@property (nonatomic , copy)void(^completeFn)(NSError * error);
@property (nonatomic , copy)void(^recieveFn)(CGFloat progress);
@end
@implementation DownloadHandle
-(void)dealloc
{
? ? [self.dataTask suspend];
? ? self.dataTask = nil;
? ? [self.outputStream close];
? ? self.outputStream = nil;
}
/**
初始化函數(shù)
@param url 下載地址
@param filePath 文件名
@param recieveFn 接受到數(shù)據(jù)的回調
@param completeFn 下載完成后的回調
@return 實例對象
*/
-(instancetype)initWithUrl:(NSString *)url
? ? ? ? ? ? ? ? ? filePath:(NSString *)filePath
? ? ? ? ? ? ? ? recieveFn:(void(^)(CGFloat progress))recieveFn
? ? ? ? ? ? ? ? completeFn:(void(^)(NSError *error))completeFn
{
? ? if(self = [super init])
? ? {
? ? ? ? _url = url;
? ? ? ? self.downloadCompletePath = filePath;
? ? ? ? self.completeFn = completeFn;
? ? ? ? self.recieveFn = recieveFn;
? ? ? ? NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
? ? ? ? NSInteger currentDataSize = [self getCurrentDataSize];
? ? ? ? NSString * range = [NSString stringWithFormat:@"bytes=%zd-",currentDataSize];
? ? ? ? if(currentDataSize != 0)
? ? ? ? ? ? _currentLength = currentDataSize;
? ? ? ? request.timeoutInterval = 0;
? ? ? ? [request setValue:range forHTTPHeaderField:@"Range"];
? ? ? ? self.dataTask = [self.session dataTaskWithRequest:request];
? ? ? ? [self.dataTask resume];
? ? }
? ? return self;
}
/**
暫停下載
*/
-(void)pauseDownload
{
? ? [self.dataTask suspend];
}
/**
繼續(xù)下載
@param recieveFn 繼續(xù)下載以后的回調
@param completeFn 下載完成的回調
*/
-(void)continueDownloadWithRecieveFn:(void(^)(CGFloat progress))recieveFn
? ? ? ? ? ? ? ? ? ? ? ? ? completeFn:(void(^)(NSError *error))completeFn
{
? ? _recieveFn = recieveFn;
? ? _completeFn = completeFn;
? ? if(self.dataTask )
? ? {
? ? ? ? NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_url]];
? ? ? ? NSInteger currentDataSize = [self getCurrentDataSize];
? ? ? ? NSString * range = [NSString stringWithFormat:@"bytes=%zd-",currentDataSize];
? ? ? ? if(currentDataSize != 0)
? ? ? ? ? ? _currentLength = currentDataSize;
? ? ? ? request.timeoutInterval = 0;
? ? ? ? [request setValue:range forHTTPHeaderField:@"Range"];
? ? ? ? self.dataTask = [self.session dataTaskWithRequest:request];
? ? ? ? [self.dataTask resume];
? ? }
}
/**
停止下載
*/
-(void)stopDownload
{
? ? [self.dataTask suspend];
? ? self.dataTask = nil;
? ? [self.outputStream close];
? ? self.outputStream = nil;
}
/**
獲取當前已下載的長度
@return 已下載的長度
*/
-(NSInteger)getCurrentDataSize
{
? ? NSFileManager * manager = [NSFileManager defaultManager];
? ? NSDictionary * dict = [manager attributesOfItemAtPath:self.downloadCompletePath error:nil];
? ? NSInteger size = [dict[@"NSFileSize"] integerValue];
? ? self.currentLength = size;
? ? return size;
}
/**
獲取當前下載進度百分比
@return 下載進度
*/
-(CGFloat)getCurrentProgress
{
? ? CGFloat progress = [self getCurrentDataSize] * 1.0 /self.totalLength;
? ? return progress;
}
#pragma mark ----------- NSURLSessionDownloadDelegate ----------
//
- (void)URLSession:(NSURLSession *)session
? ? ? ? ? dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSHTTPURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
? ? NSLog(@"接收到服務器的響應");
? ? NSLog(@"預期長度:%lld",response.expectedContentLength);
? ? self.totalLength = response.expectedContentLength + _currentLength;;
? ? //創(chuàng)建寫入流
? ? NSURL * path = [NSURL fileURLWithPath:self.downloadCompletePath];
? ? NSOutputStream * stream = [NSOutputStream outputStreamWithURL:path append:YES];
? ? [stream open];
? ? self.outputStream = stream;
? ? completionHandler(NSURLSessionResponseAllow);
}
//接受到數(shù)據(jù)后的回調 會多次回調
-(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveData:(nonnull NSData *)data
{
? ? self.currentLength += data.length;
? ? NSInteger downloadLength =? [self.outputStream write:data.bytes maxLength:data.length];
? ? CGFloat progress = 1.0 *self.currentLength / self.totalLength * 100;
? ? NSLog(@"下載了百分比---->%f %% 下載文件大小%ld,文件總大小:%ld,本地寫入的文件大新缭洹:%ld", progress,self.currentLength,self.totalLength,downloadLength);
? ? self.recieveFn(progress);
}
//下載完成
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
? ? [self.outputStream close];
? ? self.outputStream = nil;
? ? self.completeFn(error);
}
#pragma mark -------------------------懶加載--------------------------------
-(NSURLSession *)session
{
? ? if(!_session)
? ? {
? ? ? ? NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? ? ? _session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? }
? ? return _session;
}
@end