iOS 中视频下载的断点续传

       最近项目中遇到一个需求:在视频下载的时候能够暂停保存,能够显示下载进度,在下次进入界面的时候后能够继续下载,要求显示已下载的百分比;列表内能同时下载多个视频文件。思路如下:

        1、在执行下载任务时,获取本次下载文件大小,下载一部分的同时写入到本地文件中,动态显示下载进度。


        2、暂停下载。



        3、继续下载任务,获取本地已下载文件大小。获取继续下载的任务的文件大小。  



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

}

/**

初始化函数

@param url 下载地址

@param filePath 文件名

@param recieveFn 接受到数据的回调

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

}

/**

继续下载

@param recieveFn 继续下载以后的回调

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

    //创建写入流

    NSURL * path = [NSURL fileURLWithPath:self.downloadCompletePath];

    NSOutputStream * stream = [NSOutputStream outputStreamWithURL:path append:YES];

    [stream open];

    self.outputStream = stream;

    completionHandler(NSURLSessionResponseAllow);

}

//接受到数据后的回调 会多次回调

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

你可能感兴趣的:(iOS 中视频下载的断点续传)