ios 优化html表单提交,iOS 使用AFNetworking的form表单请求

首先说明下form表单请求,是一种特殊的post请求,请求方式有application/x-www-form-urlencoded、multipart/form-data、application/json。其中application/json就是我们常见的post请求,使用AFN直接请求即可。

下面开始正式的内容,如何使用AFNetworking完成form表单请求

1、application/x-www-form-urlencoded

直接上代码:

+ (AFHTTPSessionManager *)getManagerWithReqType:(requestType)reqType{

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

if(reqType == REQ_Form){

[manager.requestSerializer setValue:@"application/x-www-form-urlencoded;charset=utf-8" forHTTPHeaderField:@"Content-Type"];

}else{

manager.requestSerializer = [AFJSONRequestSerializer serializer];

manager.responseSerializer = [AFJSONResponseSerializer serializer];

[manager.requestSerializer setValue:@"application/json;text/html;charset=utf-8" forHTTPHeaderField:@"Content-Type"];

}

return manager;

}

这种form表单请求方式和我们常见的post请求方式,只有这一个地方需要区别,特别注意以下两句不能出现在application/x-www-form-urlencoded请求方式中

manager.requestSerializer = [AFJSONRequestSerializer serializer];

manager.responseSerializer = [AFJSONResponseSerializer serializer];

剩下的部分和常见的post请求一致,请求时只需要调用:

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString

parameters:(nullable id)parameters

headers:(nullable NSDictionary *)headers

progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress

success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success

failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

2、multipart/form-data

目前个人在项目中遇到的情况,主要用于上传二进制文件,使用时只需要在常见post请求的基础上,设置Content-Type为:

[manager.requestSerializer setValue:@"multipart/form-data; boundary=----WebKitFormBoundaryHzyefUottpz7ltKf"forHTTPHeaderField:@"Content-Type"];

在调用方法上稍有不同,multipart/form-data调用AFN的constructingBodyWithBlock方法:

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString

parameters:(nullable id)parameters

headers:(nullable NSDictionary *)headers

constructingBodyWithBlock:(nullable void (^)(id formData))block

progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress

success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success

failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

以上传视频为例:

+(void)uploadVideoUseAFN:(NSURL *)filePath andUrl:(NSString *)urlString{

AFHTTPSessionManager *manager = [self getManager];

/// 要上传的二进制文件

NSData *videoData = [NSData dataWithContentsOfURL:filePath];

/// 二进制文件在服务器保存的路劲

NSDateFormatter *formatter = [[NSDateFormatter alloc]init];

formatter.dateFormat =@"yyyyMMddHHmmss";

NSString *str = [formatter stringFromDate:[NSDate date]];

NSString *fileName = [NSString stringWithFormat:@"%@.mp4", str];

NSURLSessionDataTask *task = [manager POST:urlString parameters:nil headers:nil constructingBodyWithBlock:^(id _Nonnull formData) {

/// 拼接formdata

[formData appendPartWithFileData:videoData

name:@"myFile"

fileName:fileName

mimeType:@"video/mpeg"];

} progress:^(NSProgress * _Nonnull uploadProgress) {

} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

}];

[task resume];

}

疑点1、关于mimeType的设置

使用AFNetworking不需要设置额外的参数(如Content-Disposition),因为在AFNetworking完成form提交时,下面的方法会自动设置Content-Disposition为@"form-data; name=\"%@\"; filename=\"%@\"

- (void)appendPartWithFileData:(NSData *)data

name:(NSString *)name

fileName:(NSString *)fileName

mimeType:(NSString *)mimeType;

觉得不妥的也可以查看appendPartWithFileData的具体实现,会发现如下内容:

[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];

[mutableHeaders setValue:mimeType forKey:@"Content-Type"];

这里有一个痛点,就是关于mimeType的设置,图片和视频都很方便,可以直接设置为image/jpg、image/png、video/mpeg等(最好和后台对一下,因为有些开发会指定文件类型,设置不一致会请求失败)。

但对于文件上传,mimeType设置什么就比较懵,这里可以设置万能类型application/octet-stream,服务器会自动解析文件类型。关于如何获取文件的mimeType,可以查看

疑点2、关于使用AFNetworking提交Form表单,请求成功了,但是后台接收到的数据为空

正常情况下我们使用form提交,都会在header中设置:

[manager.requestSerializer setValue:@"multipart/form-data; boundary=----WebKitFormBoundaryHzyefUottpz7ltKf"forHTTPHeaderField:@"Content-Type"];

后台没有接收到传过去的数据就是因为设置了multipart/form-data和boundary。这里最坑的就是设置了multipart/form-data和boundary,还能请求成功,让人一度人为自己写的代码没有半点毛病。

解决办法:

+ (void)uploadImageWIthimageData:(NSData *)imageData{

NSString *requestUrl = @"";

/// 设置filename

NSDateFormatter *formatter = [[NSDateFormatter alloc]init];

formatter.dateFormat =@"yyyyMMddHHmmss";

NSString *str = [formatter stringFromDate:[NSDate date]];

NSString *fileName = [NSString stringWithFormat:@"%@.jpg", str];

/// 请求配置

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

/// 注意:如果返回结果是json类型按如下设置,data类型manager.responseSerializer = [AFHTTPResponseSerializer serializer];

manager.responseSerializer = [AFJSONResponseSerializer serializer];

manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html",@"image/jpeg",@"image/png",@"application/octet-stream",@"text/json",nil];

/// 设置上传参数,经过测试这个可以不用传

NSDictionary *params = @{@"file":imageData};

/// 设置header

NSDictionary *headers = @{@"Authorization":@""};

NSURLSessionDataTask *task = [manager POST:requestUrl parameters:params headers:headers constructingBodyWithBlock:^(id _Nonnull formData) {

[formData appendPartWithFileData:imageData

name:@"file"

fileName:fileName

mimeType:@"image/jpg"];

} progress:^(NSProgress * _Nonnull uploadProgress) {

} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

}];

[task resume];

}

你也不要觉得这样就不是一个multipart/form-data类型的请求了,因为AFNetworking会自动补全这一部分

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值