天天看點

iOS網絡(四):NSURLSession的使用,斷點下載下傳,離線斷點續傳,上傳檔案

NSURLSession

  • 使用步驟

        使用NSURLSession對象建立Task,然後執行Task

  • Task的類型
iOS網絡(四):NSURLSession的使用,斷點下載下傳,離線斷點續傳,上傳檔案
  •  NSURLSession的基本使用步驟代碼:
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self post];
}

-(void)get
{
    //1.确定URL
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=Alan&pwd=123&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) {
        
        //6.解析資料
        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    
    //5.執行Task
    [dataTask resume];
}

-(void)get2
{
    //1.确定URL
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=Alan&pwd=123&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=Alan&pwd=123&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];
}

@end
           

注意: completionHandler 當請求完成之後調用 !!! 在子線程中調用。是以如果有更新UI操作,請調回主線程。

  • NSURLSession使用代理下載下傳一個檔案: 
#import "ViewController.h"

@interface ViewController ()<NSURLSessionDataDelegate>
/** 接受響應體資訊 */
@property (nonatomic, strong) NSMutableData *fileData;
@end

@implementation ViewController

-(NSMutableData *)fileData
{
    if (_fileData == nil) {
        _fileData = [NSMutableData data];
    }
    return _fileData;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.url
    NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/zhidao/pic/item/86d6277f9e2f07084d0cac07e924b899a901f2a8.jpg"];
    
    //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 ----------------------
#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
{
    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]);
}


@end
           

NSURLSessionDownloadTask斷點下載下傳

#import "ViewController.h"

@interface ViewController ()<NSURLSessionDownloadDelegate>
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, strong) NSData *resumData;
@property (nonatomic, strong) NSURLSession *session;
@end

@implementation ViewController

- (IBAction)startBtnClick:(id)sender
{
    //1.url
    NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/zhidao/pic/item/86d6277f9e2f07084d0cac07e924b899a901f2a8.jpg"];
    
    //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) {
        //resumeData表示的不是檔案下載下傳大小,而是下載下傳到哪個位元組資料
        self.resumData = resumeData;
    }];
}

- (IBAction)goOnBtnClick:(id)sender
{
    NSLog(@"+++++++++++++++++++恢複下載下傳");
    //取消後繼續下載下傳
    if(self.resumData)
    {
        self.downloadTask = [self.session downloadTaskWithResumeData:self.resumData];
    }
    //暫停後下載下傳
    [self.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");
}

@end           

NSURLSessionDataTask結合NSFileHandle實作斷點下載下傳

#import "ViewController.h"

@interface ViewController ()<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;
@end

@implementation ViewController

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.url
    NSURL *url = [NSURL URLWithString:@"http://v.baidu.com/watch/2211980252341948619.html?&page=videoMultiNeed"];
    
    //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 ----------------------
#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;
}


@end           

NSURLSessionDataTask離線斷點續傳(退出App後打開繼續下載下傳)

#import "ViewController.h"
#define FileName @"121212.mp4"

@interface ViewController ()<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;
@property (nonatomic, strong)  NSURLSessionDataTask *dataTask;
@property (nonatomic, strong) NSURLSession *session;

@end

@implementation ViewController

-(void)viewDidLoad
{
    [super viewDidLoad];
    
    //1.讀取儲存的檔案總大小的資料,0
    //2.獲得目前已經下載下傳的資料的大小
    //3.計算得到進度資訊
    
}
-(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];
}

@end           

NSURLSession實作檔案上傳(NSURLSessionUploadTask)

#import "ViewController.h"
//                  ----WebKitFormBoundaryvMI3CAV0sGUtL8tr
#define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx"

#define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]

@interface ViewController ()<NSURLSessionDataDelegate>
/** 注釋 */
@property (nonatomic, strong) NSURLSession *session;
@end

@implementation ViewController

-(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.97.116.186:45632/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 ----------------------
#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);
}
@end