iOS 自己封装一个Mutipart网络请求

iOS 自己拼装Multipart网络请求

什么是Mutipart网络请求

mutipart网络请求是一种post网络请求,主要用来上传大文件,如图片、音视频数据等;

什么条件下需要自己拼装mutipart网络请求

一般的项目中我们的网络请求都是基于第三方的网络框架,如AFNetworking,但是如果我们在写SDK或者demo时,不想引用太多的第三方,就需要自己去拼装mutipart请求;

基于AFNetwoking的mutipart网络请求

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(nullable id)parameters
     constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                       success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;

通过@protocol AFMultipartFormData 中的以下协议向requet body中添加数据即可;

- (void)appendPartWithFileData:(NSData *)data
                          name:(NSString *)name
                      fileName:(NSString *)fileName
                      mimeType:(NSString *)mimeType;

代码示例

[manager POST:URLString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        
        
        switch (fileType) {
            case DBUploadFileTypeWAV:{
                NSData *data = [NSData dataWithContentsOfFile:filePath];
                NSString * nameStr = [NSString stringWithFormat:@"%@.wav",name];
                [formData appendPartWithFileData:data name:@"file" fileName:nameStr mimeType:@"audio/*"];
                
            }
                break;
            case DBUploadFileTypeMp3:{
                NSData *data = [NSData dataWithContentsOfFile:filePath];
                NSString * nameStr = [NSString stringWithFormat:@"%@.mp3",name];
                [formData appendPartWithFileData:data name:@"file" fileName:nameStr mimeType:@"audio/*"];
            }
                break;
                
            case DBUploadFileTypeImage:{
                NSString * nameStr = [NSString stringWithFormat:@"%@.png",name];
                [formData appendPartWithFileData:imageData name:@"file" fileName:nameStr mimeType:@"png"];
            }
                break;
          
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        //上传进度
        dispatch_sync(dispatch_get_main_queue(), ^{
            progress ? progress(uploadProgress) : nil;
        });
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success ? success(responseObject) : nil;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure ? failure(error) : nil;
    }];
    

基于UNSURLSession创建的Mutipart请求

1.预定义封装Mutipart需要的格式
定义post请求数据的分割线 DBUploadBoundary
static NSString *DBUploadBoundary = @"DBUploadBoundary";
定义宏定义的编码
#define DBEncode(string) [string dataUsingEncoding:NSUTF8StringEncoding]
定义换行
#define DBEnter [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]

拼接mutipart请求

-(NSData *)getDataWithPath:(NSString *)path params:(NSDictionary *)params {
    
    NSMutableData *data = [NSMutableData data];
    
    [params enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            // 拼接普通参数的上传格式.
            // 1. 普通参数上边界
            NSMutableString *headerStrM = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",DBUploadBoundary];
            // 服务器接收参数的key值.
            [headerStrM appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
            
            // 将普通参数上边界添加到请求体中
            [data appendData:[headerStrM dataUsingEncoding:NSUTF8StringEncoding]];
            
            // 2. 普通参数内容
            NSString * objValue = [NSString stringWithFormat:@"%@",obj];
            NSData *parameterData = [objValue dataUsingEncoding:NSUTF8StringEncoding];
            
            // 将普通参数内容添加到请求体中
            [data appendData:parameterData];
        }];
    [data appendData:DBEnter];
    [data appendData:DBEncode(@"--")];
    [data appendData:DBEncode(DBUploadBoundary)];
    [data appendData:DBEnter];
    [data appendData:DBEncode(@"Content-Disposition: form-data; name=\"file\"; filename=\"record.wav\"")];
    
    [data appendData:DBEnter];
    
    [data appendData:DBEncode(@"Content-Type: audio/wav")];
    [data appendData:DBEnter];
    
    [data appendData:DBEnter];

    NSData *wavData = [NSData dataWithContentsOfFile:path];
    [data appendData:wavData];
    
    [data appendData:DBEnter];
        
    [data appendData:DBEncode(@"--")];
    [data appendData:DBEncode(DBUploadBoundary)];
    [data appendData:DBEncode(@"--")];
    [data appendData:DBEnter];
    
    return data;
}

3.发起一个mutipart网络请求

代码示例

NSData *data = [self getDataWithPath:path params:mutableDict];
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    //6、获取上传的数据
    NSData *uploadData = data;
    //7、创建上传任务 上传的数据来自getData方法
    NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:uploadData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            failureBlock(error);
        }else {
            NSDictionary *contentDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];//转换数据格式
            successBlock(contentDict);
        }
        
    }];
    [task resume];

发布了35 篇原创文章 · 获赞 9 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/SunFlowerInRain/article/details/104793519