iOS 中視頻下載的斷點續(xù)傳

? ? ? ?最近項目中遇到一個需求:在視頻下載的時候能夠暫停保存,能夠顯示下載進(jìn)度,在下次進(jìn)入界面的時候后能夠繼續(xù)下載,要求顯示已下載的百分比;列表內(nèi)能同時下載多個視頻文件。思路如下:

????????1、在執(zhí)行下載任務(wù)時,獲取本次下載文件大小,下載一部分的同時寫入到本地文件中,動態(tài)顯示下載進(jìn)度。


? ? ? ? 2、暫停下載。



? ? ? ? 3、繼續(xù)下載任務(wù),獲取本地已下載文件大小。獲取繼續(xù)下載的任務(wù)的文件大小。 ?



?#import "DownloadHandle.h"

@interface? DownloadHandle ()

@property (nonatomic , copy) NSString? *? downloadCompletePath;//下載完成路徑

@property (nonatomic , strong) NSOutputStream * outputStream;//輸出流;

@property (nonatomic , assign) NSInteger currentLength;//當(dāng)前下載的長度

@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ù)的回調(diào)

@param completeFn 下載完成后的回調(diào)

@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ù)下載以后的回調(diào)

@param completeFn 下載完成的回調(diào)

*/

-(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;

}

/**

獲取當(dāng)前已下載的長度

@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;

}

/**

獲取當(dāng)前下載進(jìn)度百分比

@return 下載進(jìn)度

*/

-(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(@"接收到服務(wù)器的響應(yīng)");

? ? NSLog(@"預(yù)期長度:%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ù)后的回調(diào) 會多次回調(diào)

-(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容