美文网首页
iOS-网络-NSURLSessionUploadTask文件上

iOS-网络-NSURLSessionUploadTask文件上

作者: Imkata | 来源:发表于2019-11-15 11:36 被阅读0次

NSURLSessionUploadTask是一个文件上传类,继承于NSURLSessionDataTask。

NSURLSessionTask.png
#import "UpdateLoadVC.h"

#define UpdateImageURL @"http://www.8pmedu.com/themes/jianmo/img/upload.php"
#define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx"
#define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]

@interface UpdateLoadVC ()<NSURLSessionDelegate, NSURLSessionDataDelegate>

@end

@implementation UpdateLoadVC

- (void)viewDidLoad {
    
    [super viewDidLoad];
    self.title = @"文件上传";
}

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

/*
 AFN里面就是这样根据表单格式来封装的
 //上传操作比下载操作复杂,是通过表单这种格式来进行上传的
 表单 mulitpart/form-data; (格式)
 
 1 边界符号 要配置请求头
 
 上传都是POST: bodydata
 // 2.1 边界符号(开始边界)
 
 // 2.2 属性配置 名字;key;类型
 
 // 2.3 拼接数据(配置数据+文件数据)
 
 // 2.4 边界符号 (结束边界)
 */

- (void)netUpdateImage{
    
    NSURL *url = [NSURL URLWithString:UpdateImageURL];
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    
    //请求体
    NSMutableData *bodyData = [self getBodyDataWithRequest:request];
    
    //设置请求体
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:bodyData];
    
    //回话对象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    
    //请求task
    /*
     第一个参数:请求对象
     第二个参数:传递是要上传的数据(请求体)
     第三个参数:
     */
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData: bodyData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        //解析
        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    
    //执行Task
    [uploadTask resume];
}

- (NSMutableData *)getBodyDataWithRequest:(NSMutableURLRequest *)request {
    
    //1 边界符号要配置请求头里面去
    /*
     multipart/form-data 是表单格式
     charset=utf-8 是utf-8编码
     bounary 是表单开头
     */
    [request setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", Kboundary] forHTTPHeaderField:@"Content-Type"];
    
    /// body
    NSMutableData *boydData = [NSMutableData data];
    // 2.1 边界符号(开始边界)
    // body每一个段内容以换行符作为结束标示
    NSString *fileBeginBoundary = [NSString stringWithFormat:@"--%@\r\n", Kboundary];
    [boydData appendData:[fileBeginBoundary dataUsingEncoding:NSUTF8StringEncoding]];
    
    // 2.2 属性配置 名字;key;类型
    
    NSString *serverFileKey = @"image";  //key
    NSString *serverFileName = @"eoc123111.png";  //name
    NSString *serverContentTypes = @"image/png";  //类型
    
    // filename已命名文件;  name相当于一个key, 这个名字和服务器保持一致
    /*
     理解key,表单发送给服务端,服务端拿到数据之后,可以将任务解析成一个字典了imageDict;图片数据会通过这个字典里面的name来获取图片(伪代码 image =  imageDict[serverFileKey])
     */
    //2.3 拼接数据(创建一个字符串来拼装)
    NSMutableString *string = [NSMutableString new];
    [string appendFormat:@"Content-Disposition:form-data; name=\"%@\"; filename=\"%@\" ", serverFileKey, serverFileName];
    [string appendFormat:@"%@", KNewLine];
    [string appendFormat:@"Content-Type:%@", serverContentTypes];
    [string appendFormat:@"%@", KNewLine];
    [string appendFormat:@"%@", KNewLine];
    [boydData appendData:[string dataUsingEncoding:NSUTF8StringEncoding]];
    
    // 2.3 拼接数据(拼接文件数据)
    UIImage *image = [UIImage imageNamed:@"1.png"];
    NSData *imageData = UIImagePNGRepresentation(image);
    [boydData appendData:imageData];
    
    // 2.4 边界符号 (结束边界)
    NSString *fileEndBoundary = [NSString stringWithFormat:@"\r\n--%@", Kboundary];
    [boydData appendData:[fileEndBoundary dataUsingEncoding:NSUTF8StringEncoding]];
    
    return boydData;
}

#pragma mark NSURLSessionDataDelegate

// 1响应
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
    
    completionHandler(NSURLSessionResponseAllow);
}

// 上传进度
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
    
    //每包发送的大小bytesSent,totalBytesSent已经上传了多少;totalBytesExpectedToSend总共要发送多少
    // 32768 = 32KB
    NSLog(@"didSendBodyData: %ld--%ld-%ld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
    
}

// 2 接收数据
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    
    NSDictionary *infoDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@", infoDict);
    
}

// 3 完成
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    
}
@end

解释

  1. 文件上传主要是根据表单格式来拼接数据,AFN里面文件上传也是这样封装的。
  2. 上传进度可以在- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;监听到。

Demo地址:NetOne

相关文章

网友评论

      本文标题:iOS-网络-NSURLSessionUploadTask文件上

      本文链接:https://www.haomeiwen.com/subject/joijictx.html