AFNetWorking 上传功能使用及源码分析

使用方法比较多,这里列举两种:

第一种:

// 1. 使用AFHTTPSessionManager的接口
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    [manager POST:@"http://123.123.123.1" parameters:@{@"aaa":@"111"} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        // 在这个block中设置需要上传的文件
        NSString *path = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"jpg"];
        // 将本地图片数据拼接到formData中 指定name
//        [formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"image" error:nil];
        
//        //     或者使用这个接口拼接 指定name和filename
        NSData *picdata  =[NSData dataWithContentsOfFile:path];
        [formData appendPartWithFileData:picdata name:@"image" fileName:@"image.jpg" mimeType:@"image/jpeg"];
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        NSLog(@"progress --- %@",uploadProgress.localizedDescription);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"responseObject-------%@", responseObject);
        dispatch_async(dispatch_get_main_queue(), ^{
            self.tvres.text = [NSString stringWithFormat:@"响应结果:%@",responseObject];
        });
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"Error-------%@", error);
    }];
    

第二种:

 AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    // request
    NSURL *url = [NSURL URLWithString:@"http://114.215.186.169:9002/api/demo/test/file"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];
    // bodydata
    //(2)请求头
    //上传任务,必须要添加的字段
    // 分隔符
    //multipart/form-data是必须的,是指提交的表单中有附件
    /*
     Multipart协议是基于post方法的组合实现,和post协议的主要区别在于请求头和请求体的不同
     multipart/form-data的请求头必须包含一个特殊的头信息:Content-Type,且其值也必须规定为multipart/form-data,同时还需要规定一个内容分割符用于分割请求体中的多个post的内容,如文件内容和文本内容自然需要分割开来,不然接收方就无法正常解析和还原这个文件了
     multipart/form-data的请求体也是一个字符串,不过和post的请求体不同的是它的构造方式,post是简单的name=value值连接,而multipart/form-data则是添加了分隔符等内容的构造体
     
     */
    NSString *boundary = @"---------------------------7db15a14291cce";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; charset=utf-8;boundary=%@",boundary];
    // 设置Content-Type
    [request setValue:contentType forHTTPHeaderField:@"Content-Type"];

   //(3)请求体
    NSMutableString *startStr = [NSMutableString string];
    // 拼接头部格式
    [startStr appendFormat:@"--%@\r\n",boundary];
    [startStr appendFormat:@"Content-disposition: form-data; name=\"image\"; filename=\"image.jpg\""];
    [startStr appendFormat:@"\r\n"];
    [startStr appendFormat:@"Content-Type: application/octet-stream"];
    [startStr appendFormat:@"\r\n\r\n"];

    
    NSMutableData *bodyData = [NSMutableData data];
    NSData *startData = [startStr dataUsingEncoding:NSUTF8StringEncoding];
    [bodyData appendData:startData];


    // 拼接上传文件数据
    NSString *path = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"jpg"];
    NSData *picdata  =[NSData dataWithContentsOfFile:path];
    [bodyData appendData:picdata];


    // 拼接结尾格式
    NSString *endStr = [NSString stringWithFormat:@"\r\n--%@--\r\n",boundary];
    NSData *endData = [endStr dataUsingEncoding:NSUTF8StringEncoding];
    [bodyData appendData:endData];


   NSURLSessionUploadTask *uploadtask = [sessionManager uploadTaskWithRequest:request fromData:bodyData progress:^(NSProgress * _Nonnull uploadProgress) {
        NSLog(@"progress --- %@",uploadProgress.localizedDescription);
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {

        NSLog(@"completion --- error:%@",error);
    }];
    [uploadtask resume];

第二种是靠自己拼凑http header 和 body用于发送给服务端,下面主要分析第一种方法源码的实现。

1 首先进入Post源码

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
     constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
                      progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
   
    NSError *serializationError = nil;
     //最复杂的在这块
    NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
    if (serializationError) {
        if (failure) {
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
        }

        return nil;
    }
   __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
        if (error) {
            if (failure) {
                failure(task, error);
            }
        } else {
            if (success) {
                success(task, responseObject);
            }
        }
    }];

    [task resume];

    return task;
}

首先是创建需要的NSURLRequest,然后新建task,返回task,这里重点说一下标红的地方,NSURLRequest如何组成。

multipart

猜你喜欢

转载自www.cnblogs.com/xiaonanxia/p/9728449.html