• NSURLSession


    一、基本使用

    -(void)get
    {
        //1.确定URL
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=hello&pwd=world&type=JSON"];
        //2.创建请求对象
        NSURLRequest *request =[NSURLRequest requestWithURL:url];
        //3.创建会话对象
        NSURLSession *session = [NSURLSession sharedSession];
        //4.创建Task
        /*
         第一个参数:请求对象
         第二个参数:completionHandler 当请求完成之后调用
            data:响应体信息
            response:响应头信息
            error:错误信息当请求失败的时候 error有值
         */
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //5.解析数据
            NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }];
        //6.执行Task
        [dataTask resume];
    }
    
    -(void)get2
    {
        //1.确定URL
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
        //2.创建请求对象
        //NSURLRequest *request =[NSURLRequest requestWithURL:url];
        //3.创建会话对象
        NSURLSession *session = [NSURLSession sharedSession];
        //4.创建Task
        /*
         第一个参数:请求路径
         第二个参数:completionHandler 当请求完成之后调用
         data:响应体信息
         response:响应头信息
         error:错误信息当请求失败的时候 error有值
         注意:dataTaskWithURL 内部会自动的将请求路径作为参数创建一个请求对象(GET)
         */
        NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //6.解析数据
            NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }];
        //5.执行Task
        [dataTask resume];
    }
    -(void)post
    {
        //1.确定URL
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
        //2.创建请求对象
        NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url];
        //2.1 设置请求方法为post
        request.HTTPMethod = @"POST";
        //2.2 设置请求体
        request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
        //3.创建会话对象
        NSURLSession *session = [NSURLSession sharedSession];
        //4.创建Task
        /*
         第一个参数:请求对象
         第二个参数:completionHandler 当请求完成之后调用 !!! 在子线程中调用
         data:响应体信息
         response:响应头信息
         error:错误信息当请求失败的时候 error有值
         */
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"%@",[NSThread currentThread]);
            //6.解析数据
            NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }];
        //5.执行Task
        [dataTask resume];
    }
    

     二、NSURLSession代理方法

    <NSURLSessionDataDelegate>
    /** 接受响应体信息 */
    @property (nonatomic, strong) NSMutableData *fileData;
    {
        if (_fileData == nil) {
            _fileData = [NSMutableData data];
        }
        return _fileData;
    }
    //请求
     //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"];
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        //3.创建会话对象,设置代理
        /*
         第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
         第二个参数:代理
         第三个参数:设置代理方法在哪个线程中调用
         */
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        //4.创建Task
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
        //5.执行Task
        [dataTask resume];
    //代理方法
    **
     *  1.接收到服务器的响应 它默认会取消该请求
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param response          响应头信息
     *  @param completionHandler 回调 传给系统
     */
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
    {
        NSLog(@"%s",__func__);
        
        /*
         NSURLSessionResponseCancel = 0,取消 默认
         NSURLSessionResponseAllow = 1, 接收
         NSURLSessionResponseBecomeDownload = 2, 变成下载任务
         NSURLSessionResponseBecomeStream        变成流
         */
        completionHandler(NSURLSessionResponseAllow);
    }
    /**
     *  接收到服务器返回的数据 调用多次
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param data              本次下载的数据
     */
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    {
         NSLog(@"%s",__func__);
        //拼接数据
        [self.fileData appendData:data];
    }
    /**
     *  请求结束或者是失败的时候调用
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param error             错误信息
     */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
         NSLog(@"%s",__func__);
        //解析数据
        NSLog(@"%@",[[NSString alloc]initWithData:self.fileData encoding:NSUTF8StringEncoding]);
    }
    

      

    三、大文件下载

        //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"];
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        //3.创建session
        NSURLSession *session = [NSURLSession sharedSession];
        //4.创建Task
        /*
         第一个参数:请求对象
         第二个参数:completionHandler 回调
            location:
            response:响应头信息
            error:错误信息
         */
        //该方法内部已经实现了边接受数据边写沙盒(tmp)的操作
        NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //6.处理数据
            NSLog(@"%@---%@",location,[NSThread currentThread]);
            //6.1 拼接文件全路径
            NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
            //6.2 剪切文件
            [[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
            NSLog(@"%@",fullPath);
        }];
        //7.执行Task
        [downloadTask resume];
    }
    

      2.大文件下载

    /优点:不需要担心内存
    //缺点:无法监听文件下载进度
    -(void)download
    {
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"];
        
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        //3.创建session
        NSURLSession *session = [NSURLSession sharedSession];
        
        //4.创建Task
        /*
         第一个参数:请求对象
         第二个参数:completionHandler 回调
            location:
            response:响应头信息
            error:错误信息
         */
        //该方法内部已经实现了边接受数据边写沙盒(tmp)的操作
        NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            //6.处理数据
            NSLog(@"%@---%@",location,[NSThread currentThread]);
            
            //6.1 拼接文件全路径
            NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
            
            //6.2 剪切文件
            [[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
            NSLog(@"%@",fullPath);
        }];
        
        //7.执行Task
        [downloadTask resume];
    }
    
    -(void)delegate
    {
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"];
        
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        //3.创建session
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        
        //4.创建Task
        NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
        
        //5.执行Task
        [downloadTask resume];
    }
    
    #pragma mark ----------------------
    #pragma mark NSURLSessionDownloadDelegate
    /**
     *  写数据
     *
     *  @param session                   会话对象
     *  @param downloadTask              下载任务
     *  @param bytesWritten              本次写入的数据大小
     *  @param totalBytesWritten         下载的数据总大小
     *  @param totalBytesExpectedToWrite  文件的总大小
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
        //1. 获得文件的下载进度
        NSLog(@"%f",1.0 * totalBytesWritten/totalBytesExpectedToWrite);
    }
    
    /**
     *  当恢复下载的时候调用该方法
     *
     *  @param fileOffset         从什么地方下载
     *  @param expectedTotalBytes 文件的总大小
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        NSLog(@"%s",__func__);
    }
    
    /**
     *  当下载完成的时候调用
     *
     *  @param location     文件的临时存储路径
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        NSLog(@"%@",location);
        //1 拼接文件全路径
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
        //2 剪切文件
        [[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
        NSLog(@"%@",fullPath);
    }
    /**
     *  请求结束
     */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
        NSLog(@"didCompleteWithError");
    }
    

      3.下载

    @interface ViewController ()<NSURLSessionDownloadDelegate>
    @property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
    @property (nonatomic, strong) NSData *resumData;
    @property (nonatomic, strong) NSURLSession *session;
    @implementation ViewController
    - (IBAction)startBtnClick:(id)sender
    { //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]; 
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        //3.创建session
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        //4.创建Task
        NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
        //5.执行Task
        [downloadTask resume];
        self.downloadTask = downloadTask;
    }
    //暂停是可以恢复
    - (IBAction)suspendBtnClick:(id)sender
    { NSLog(@"+++++++++++++++++++暂停");
        [self.downloadTask suspend];
    }
    //cancel:取消是不能恢复
    //cancelByProducingResumeData:是可以恢复
    - (IBAction)cancelBtnClick:(id)sender
    {
        NSLog(@"+++++++++++++++++++取消");
        //[self.downloadTask cancel];
        //恢复下载的数据!=文件数据
        [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
            self.resumData = resumeData;
        }];
    }
    - (IBAction)goOnBtnClick:(id)sender
    {
        NSLog(@"+++++++++++++++++++恢复下载");
        if(self.resumData)
        {
            self.downloadTask = [self.session downloadTaskWithResumeData:self.resumData];
        }
        [self.downloadTask resume];
    }
    //优点:不需要担心内存
    //缺点:无法监听文件下载进度
    -(void)download
    {
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"];
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        //3.创建session
        NSURLSession *session = [NSURLSession sharedSession];
        //4.创建Task
        /*
         第一个参数:请求对象
         第二个参数:completionHandler 回调
            location:
            response:响应头信息
            error:错误信息
         */
        //该方法内部已经实现了边接受数据边写沙盒(tmp)的操作
        NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //5.处理数据
            NSLog(@"%@---%@",location,[NSThread currentThread]);
            //5.1 拼接文件全路径
            NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
            //5.2剪切文件
            [[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
            NSLog(@"%@",fullPath);
        }];
        //6.执行Task
        [downloadTask resume];
    }
    #pragma mark ----------------------
    #pragma mark NSURLSessionDownloadDelegate
    /**
     *  写数据
     *
     *  @param session                   会话对象
     *  @param downloadTask              下载任务
     *  @param bytesWritten              本次写入的数据大小
     *  @param totalBytesWritten         下载的数据总大小
     *  @param totalBytesExpectedToWrite  文件的总大小
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {//1. 获得文件的下载进度
        NSLog(@"%f",1.0 * totalBytesWritten/totalBytesExpectedToWrite);
    }
    
    /**
     *  当恢复下载的时候调用该方法
     *
     *  @param fileOffset         从什么地方下载
     *  @param expectedTotalBytes 文件的总大小
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {NSLog(@"%s",__func__);
    }
    /**
     *  当下载完成的时候调用
     *
     *  @param location     文件的临时存储路径
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        NSLog(@"%@",location);
        //1 拼接文件全路径
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
        //2 剪切文件
        [[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
        NSLog(@"%@",fullPath);
    }
    /**
     *  请求结束
     */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
        NSLog(@"didCompleteWithError");
    }
    

      2.通过文件句柄下载

    <NSURLSessionDataDelegate>
    @property (weak, nonatomic) IBOutlet UIProgressView *proessView;
    /** 接受响应体信息 */
    @property (nonatomic, strong) NSFileHandle *handle;
    @property (nonatomic, assign) NSInteger totalSize;
    @property (nonatomic, assign) NSInteger currentSize;
    @property (nonatomic, strong) NSString *fullPath;
    - (void)loadData{
    //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        //3.创建会话对象,设置代理
        /*
         第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
         第二个参数:代理
         第三个参数:设置代理方法在哪个线程中调用
         */
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        //4.创建Task
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
        //5.执行Task
        [dataTask resume];
    }
    #pragma mark NSURLSessionDataDelegate
    /**
     *  1.接收到服务器的响应 它默认会取消该请求
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param response          响应头信息
     *  @param completionHandler 回调 传给系统
     */
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
    {
        //获得文件的总大小
        self.totalSize = response.expectedContentLength;
        //获得文件全路径
        self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
        //创建空的文件
        [[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
        //创建文件句柄
        self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
        [self.handle seekToEndOfFile];
        /*
         NSURLSessionResponseCancel = 0,取消 默认
         NSURLSessionResponseAllow = 1, 接收
         NSURLSessionResponseBecomeDownload = 2, 变成下载任务
         NSURLSessionResponseBecomeStream        变成流
         */
        completionHandler(NSURLSessionResponseAllow);
    }
    /**
     *  接收到服务器返回的数据 调用多次
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param data              本次下载的数据
     */
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    {
        //写入数据到文件
        [self.handle writeData:data];
        //计算文件的下载进度
        self.currentSize += data.length;
        NSLog(@"%f",1.0 * self.currentSize / self.totalSize);
        self.proessView.progress = 1.0 * self.currentSize / self.totalSize;
    }
    /**
     *  请求结束或者是失败的时候调用
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param error             错误信息
     */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
        NSLog(@"%@",self.fullPath);
        //关闭文件句柄
        [self.handle closeFile];
        self.handle = nil;
    }
    

      3.文件断点续传

    @property (weak, nonatomic) IBOutlet UIProgressView *proessView;
    /** 接受响应体信息 */
    @property (nonatomic, strong) NSFileHandle *handle;
    @property (nonatomic, assign) NSInteger totalSize;
    @property (nonatomic, assign) NSInteger currentSize;
    @property (nonatomic, strong) NSString *fullPath;
    @property (nonatomic, strong)  NSURLSessionDataTask *dataTask;
    @property (nonatomic, strong) NSURLSession *session;
    -(NSString *)fullPath
    {
        if (_fullPath == nil) {
            
            //获得文件全路径
            _fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:FileName];
        }
        return _fullPath;
    }
    
    -(NSURLSession *)session
    {
        if (_session == nil) {
            //3.创建会话对象,设置代理
            /*
             第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
             第二个参数:代理
             第三个参数:设置代理方法在哪个线程中调用
             */
            _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        }
        return _session;
    }
    -(NSURLSessionDataTask *)dataTask
    {
        if (_dataTask == nil) {
            //1.url
            NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
            
            //2.创建请求对象
            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
            
            //3 设置请求头信息,告诉服务器请求那一部分数据
            self.currentSize = [self getFileSize];
            NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
            [request setValue:range forHTTPHeaderField:@"Range"];
            
            //4.创建Task
            _dataTask = [self.session dataTaskWithRequest:request];
        }
        return _dataTask;
    }
    
    -(NSInteger)getFileSize
    {
        //获得指定文件路径对应文件的数据大小
        NSDictionary *fileInfoDict = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
        NSLog(@"%@",fileInfoDict);
        NSInteger currentSize = [fileInfoDict[@"NSFileSize"] integerValue];
        
        return currentSize;
    }
    - (IBAction)startBtnClick:(id)sender
    {
        [self.dataTask resume];
    }
    
    - (IBAction)suspendBtnClick:(id)sender
    {
        NSLog(@"_________________________suspend");
        [self.dataTask suspend];
    }
    
    //注意:dataTask的取消是不可以恢复的
    - (IBAction)cancelBtnClick:(id)sender
    {
          NSLog(@"_________________________cancel");
        [self.dataTask cancel];
        self.dataTask = nil;
    }
    
    - (IBAction)goOnBtnClick:(id)sender
    {
          NSLog(@"_________________________resume");
        [self.dataTask resume];
    }
    
    #pragma mark ----------------------
    #pragma mark NSURLSessionDataDelegate
    /**
     *  1.接收到服务器的响应 它默认会取消该请求
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param response          响应头信息
     *  @param completionHandler 回调 传给系统
     */
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
    {
        //获得文件的总大小
        //expectedContentLength 本次请求的数据大小
        self.totalSize = response.expectedContentLength + self.currentSize;
        
        if (self.currentSize == 0) {
            //创建空的文件
            [[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
            
        }
        //创建文件句柄
        self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
        
        //移动指针
        [self.handle seekToEndOfFile];
        
        /*
         NSURLSessionResponseCancel = 0,取消 默认
         NSURLSessionResponseAllow = 1, 接收
         NSURLSessionResponseBecomeDownload = 2, 变成下载任务
         NSURLSessionResponseBecomeStream        变成流
         */
        completionHandler(NSURLSessionResponseAllow);
    }
    
    /**
     *  接收到服务器返回的数据 调用多次
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param data              本次下载的数据
     */
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    {
        //写入数据到文件
        [self.handle writeData:data];
        //计算文件的下载进度
        self.currentSize += data.length;
        NSLog(@"%f",1.0 * self.currentSize / self.totalSize);
        self.proessView.progress = 1.0 * self.currentSize / self.totalSize;
    }
    /**
     *  请求结束或者是失败的时候调用
     *
     *  @param session           会话对象
     *  @param dataTask          请求任务
     *  @param error             错误信息
     */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {  NSLog(@"%@",self.fullPath);
        //关闭文件句柄
        [self.handle closeFile];
        self.handle = nil;
    }
    -(void)dealloc
    {  //清理工作
        //finishTasksAndInvalidate
        [self.session invalidateAndCancel];
    }
    

      4、文件上传

    #define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx"
    #define KNewLine [@"
    " dataUsingEncoding:NSUTF8StringEncoding]
    @interface ViewController ()<NSURLSessionDataDelegate>
    /** 注释 */
    @property (nonatomic, strong) NSURLSession *session;
    -(NSURLSession *)session
    {
        if (_session == nil) {
            NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
            
            //是否运行蜂窝访问
            config.allowsCellularAccess = YES;
            config.timeoutIntervalForRequest = 15;
            
            _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        }
        return _session;
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self upload2];
    }
    
    -(void)upload
    {
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
        
        //2.创建请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        //2.1 设置请求方法
        request.HTTPMethod = @"POST";
    
        //2.2 设请求头信息
        [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];
        
        //3.创建会话对象
    //    NSURLSession *session = [NSURLSession sharedSession];
        
        //4.创建上传TASK
        /*
         第一个参数:请求对象
         第二个参数:传递是要上传的数据(请求体)
         第三个参数:
         */
       NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
           
           //6.解析
           NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }];
        
        //5.执行Task
        [uploadTask resume];
    }
    
    -(void)upload2
    {
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
        
        //2.创建请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        //2.1 设置请求方法
        request.HTTPMethod = @"POST";
        
        //2.2 设请求头信息
        [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];
        
        //3.创建会话对象
        
        //4.创建上传TASK
        /*
         第一个参数:请求对象
         第二个参数:传递是要上传的数据(请求体)
         */
        NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            //6.解析
            NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }];
        //5.执行Task
        [uploadTask resume];
    }
    -(NSData *)getBodyData
    {
        NSMutableData *fileData = [NSMutableData data];
        //5.1 文件参数
        /*
         --分隔符
         Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png"
         Content-Type: image/png(MIMEType:大类型/小类型)
         空行
         文件参数
         */
        [fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [fileData appendData:KNewLine];
        //name:file 服务器规定的参数
        //filename:Snip20160225_341.png 文件保存到服务器上面的名称
        //Content-Type:文件的类型
        [fileData appendData:[@"Content-Disposition: form-data; name="file"; filename="Sss.png"" dataUsingEncoding:NSUTF8StringEncoding]];
        [fileData appendData:KNewLine];
        [fileData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
        [fileData appendData:KNewLine];
        [fileData appendData:KNewLine];
        
        UIImage *image = [UIImage imageNamed:@"Snip20160226_90"];
        //UIImage --->NSData
        NSData *imageData = UIImagePNGRepresentation(image);
        [fileData appendData:imageData];
        [fileData appendData:KNewLine];
        //5.2 非文件参数
        /*
         --分隔符
         Content-Disposition: form-data; name="username"
         空行
         123456
         */
        [fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [fileData appendData:KNewLine];
        [fileData appendData:[@"Content-Disposition: form-data; name="username"" dataUsingEncoding:NSUTF8StringEncoding]];
        [fileData appendData:KNewLine];
        [fileData appendData:KNewLine];
        [fileData appendData:[@"123456" dataUsingEncoding:NSUTF8StringEncoding]];
        [fileData appendData:KNewLine];
        //5.3 结尾标识
        /*
         --分隔符--
         */
        [fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
        return fileData;
    }
    #pragma mark NSURLSessionDataDelegate
    /*
     *  @param bytesSent                本次发送的数据
     *  @param totalBytesSent           上传完成的数据大小
     *  @param totalBytesExpectedToSend 文件的总大小
     */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
    {
        NSLog(@"%f",1.0 *totalBytesSent / totalBytesExpectedToSend);
    }
    

      

  • 相关阅读:
    win7如何配置access数据源
    pcA降维算法
    今天的分类
    实现MFC菜单画笔画圆,并且打钩
    多个字符串输出,竖直输出
    端口重用
    安卓快速关机APP
    端口转发
    学习OpenCV
    求解数独
  • 原文地址:https://www.cnblogs.com/TheYouth/p/6822682.html
Copyright © 2020-2023  润新知