iOS网络-NSURLSessionDataTask大文件离线断点下载

什么叫离线断点下载,就是用户下载中关闭程序重新打开可以继续下载

代码实现如下:

#import "ViewController.h"
@interface ViewController ()<NSURLSessionDataDelegate>
//输出流
@property (nonatomic, strong) NSOutputStream *stream ;
//Task对象
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
//文件总大小
@property (nonatomic, assign) NSInteger totalSize;
//文件当前已下载大小
@property (nonatomic, assign) NSInteger currentSize;
//文件的全路径
@property (nonatomic, strong) NSString *fullPath
//会话对象
@property (nonatomic, strong) NSURLSession *session;
@end

@implementation ViewController
//懒加载会话对象
-(NSURLSession *)session
{
    if (_session == nil) {
        //3.创建会话对象
        /*
         第一个参数:配置信息
         第二个参数:代理  self
         第三个参数:代理方法的队列
         */
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        _session = session;
    }
    return _session;
}
//懒加载task
-(NSURLSessionDataTask *)dataTask
{
    if (_dataTask == nil) {

        //1.确定请求路径
        NSString *urlStr = @"http://120.25.226.186:32812/resources/videos/minion_01.mp4";
        NSURL *url = [NSURL URLWithString:urlStr];

        //2.创建请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        NSString *fileName = [urlStr lastPathComponent];
        NSInteger curentSize = [self getCurrentLength:fileName];
                 //记录当前已下载的大小
        self.currentSize = curentSize;
        //设置请求头,表示下一次下载从哪个地方开始下载
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-",curentSize];
        [request setValue:range forHTTPHeaderField:@"Range"];

        //4.创建task
        NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];

        _dataTask = dataTask;

    }
    return _dataTask;
}

-(void)dealloc
{
    //释放session 俩种方法任选一种
    [self.session invalidateAndCancel];
//    [self.session resetWithCompletionHandler:nil];
}

//开始下载
- (IBAction)startBtnClick:(id)sender
{
    [self.dataTask resume];
}
//暂停下载
- (IBAction)suspendBtnClick:(id)sender
{
    [self.dataTask suspend];
}
//继续下载
- (IBAction)goOnBtnClick:(id)sender
{
    [self.dataTask resume];
}
//得到当前下载进度
-(NSInteger)getCurrentLength:(NSString *)fileName
{
    self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName];

    NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:self.fullPath error:nil];
    NSLog(@"%@",dict);
    //获取文件已下载大小
    NSInteger size = [dict[@"NSFileSize"] integerValue];
    return size;
}
#pragma mark - NSURLSessionDataDelegate
//1.接收到服务器响应的时候
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
    //expectedContentLength:本次请求的数据的大小
    self.totalSize = response.expectedContentLength + self.currentSize;


    //创建输出流
    NSOutputStream *stream = [[NSOutputStream alloc]initToFileAtPath:self.fullPath append:YES];

    //打开流
    [stream open];
    self.stream = stream;

    //通过该回调告诉系统是否要继续接收服务器返回给我们的数据NSURLSessionResponseAllow==接收
    completionHandler(NSURLSessionResponseAllow);
}
//2.接收到服务器返回数据的时候调用,会调用多次
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    NSLog(@"didReceiveData---%zd",data.length);

    [self.stream write:data.bytes maxLength:data.length];

    self.currentSize +=data.length;
   //打印下载进度
    NSLog(@"%f",1.0 * self.currentSize / self.totalSize);
}

//3.请求结束的时候调用(成功|失败),如果失败那么error有值
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"didCompleteWithError---%@",[NSThread currentThread]);

  //关闭流
    [self.stream close];
    self.stream = nil;
}
@end
原文地址:https://www.cnblogs.com/liugengqun/p/5140141.html