POST发送form-data的一些总结

原创 2016年03月18日 14:19:42

接手的项目是要将IOS上的SDK移植到Mac上使用,取到IOS版本的SDK代码阅读后发现仍然在使用ASIHttpReqest作为网络请求的模块,但是众所周知ASIHttpReqest已经停止更新已有4年之久,虽然ASIHttpReqest是一个非常优秀的网络库,但因为缺少社区维护,随着技术的发展,还是有一定的局限。

相比之下AFNetworking是替代ASIHTTPRequest最佳之选。所以决定先将SDK功能业务部分采用AFNetworking进行代码重构[AFNetworking和ASIHTTPRequest的比较]

原先IOS版本的SDK直接使用ASIFormDataRequest通过setPostValue将要发送的数据一个一个添加到postData中,开始采用AFNetworking之后直接使用AFHTTPSessionManager中

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure


发现,POST的数据在服务端被认为是缺少数据,同样是POST操作,为什么会有不同的结果呢?使用Charles抓包分析后,发现使用AFHTTPSessionManager发送的数据是MultiPart,ASIHTTPRequest发送的是x-www-form-urlencoded类型,所以判断服务器只能接收x-www-form-urlencoded类型的数据,也就是&key=value样式的。

继续上网查资料,POST发送数据,但是会有多种数据提交格式,[四种常见的POST提交数据方式]查看了AFNetworking中POST代码后,发现使用到的Content-Type是multipart/form-data。至此找到服务器对我使用AFHTTPSessionManager发送的POST数据被认为不完整的原因。

于是直接使用NSURLConnection写了以下的方法实现POST发送form-data到服务端。


+(void)universalRequestWith:(NSDictionary *)parameters URLStr:(NSString *)URLStr method:(RequestMethodType)methodType andBlock:(void (^)(NSDictionary *response, NSError *error))block{
    NSURL *url=[NSURL URLWithString:URLStr];
    
    
    
    if (methodType == RequestMethodPostType) {
        dispatch_queue_t myCustomQueue = dispatch_queue_create("com.myown.UniversalRequestQueue", NULL);
        dispatch_async(myCustomQueue, ^(){
            NSMutableData *postBody=[NSMutableData data];
            NSUInteger i=0;
            for (NSString *key in [parameters allKeys]) {
                NSString *data = [NSString stringWithFormat:@"%@=%@%@", key, [parameters valueForKey:key],(i<[[parameters allKeys] count]-1 ?  @"&" : @"")];
                [postBody appendData:[data dataUsingEncoding:NSUTF8StringEncoding]];
                i++;
            }
            NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:url
                                                                     cachePolicy:NSURLRequestReloadIgnoringCacheData
                                                                 timeoutInterval:20.0f];
            [request setHTTPMethod: @"POST"];
            [request setValue: @"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
            [request setHTTPBody:postBody];
            
            NSError *error = nil;
            NSDictionary *result = [[NSDictionary alloc]init];
            NSHTTPURLResponse* urlResponse = nil;
            
            NSData *responseData = [NSURLConnection sendSynchronousRequest:request
                                                         returningResponse:&urlResponse error:&error];
            if (error.code==0) {
                
                result =[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
            }
            
            dispatch_async(dispatch_get_main_queue(), ^(){
                
                if (block) {
                    block(result,error);
                }
            });
        });
    }

}


再对POST提交数据的方式进行仔细研究,发现其中application/x-www-form-urlencoded编码其实是基于uri的percent-encoding编码的,所以采用application/x-www-form-urlencoded的POST数据和queryString只是形式不同,本质都是传递参数。哪是否意味着可以直接使用GET方式去提交参数呢?

于是使用了AFHTTPSessionManager的

- (NSURLSessionDataTask *)GET:(NSString *)URLString
                   parameters:(id)parameters
                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure

最终发现,数据提交成功,返回了正确的结果。

接下来对AFNetworking再仔细研究。

但是又有疑虑,既然AFNetworking应该更全面,为什么会没有支持application/x-www-form-urlencoded的处理方式呢?在源码中搜索application/x-www-form-urlencoded,发现AFURLRequestSerialization的方法

- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(id)parameters
                                        error:(NSError *__autoreleasing *)error

中是有使用application/x-www-form-urlencoded作为Content-Type来封装Http请求的,使用效果怎么样?简单写了一段测试,用AFHTTPSessionManager的requestSerializer去调用AFNetworking提供的封装方法,也是可以得到正确的结果。

    NSError *error;
    NSHTTPURLResponse* urlResponse = nil;
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:URLStr]];
   NSURLRequest *AFRequest = [manager.requestSerializer requestBySerializingRequest:[request copy] withParameters:parameters error:&error];
    NSData *responseData = [NSURLConnection sendSynchronousRequest:AFRequest
                                                 returningResponse:&urlResponse error:&error];
    NSDictionary *result =[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];

综上,解决了form-data的提交,也对POST不同的数据提交方式有了初步的认识和了解,该类问题以后处理起来也将更游刃有余。


版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Multipart/form-data POST文件上传详解

Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下:   ...

Ajax利用FormData提交文件和数据

一、ajax提交纯表单(不包含文件或二进制或非ASCII数据)      ajax提交表单绕了很久,遇到一些问题进行测试下以加深理解,测试使用浏览器 49.0.2623.110 m,HTML使用HT...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

iOS之网络请求之AFN表单上传之form-data

表单上传呢一般是当要上传图片的时候用的网络请求方式。上传http post请求的表单格式是这样的Content-type: multipart/form-data, boundary=qwerdf ...

HTTP协议与HTTP表单传输格式,再论get、post方法

HTTP的GET/POST方式有何区别?这是一个老生常谈的问题,但老生常谈的问题往往有一些让人误解的结论。本文将带您浅尝HTTP协议,在了解HTTP协议的同时将会展示许多被人们忽视的内容。在掌握了HT...

Http post请求 entity body的格式

Http post请求 entity body的格式,有三种格式,具体使用哪一种,由消息头当中ContentType的值所决定 1. ContentType:multipart/form-data;...

POST发送form-data的一些总结

1.POST发送数据的不同方式和相互区别; 2.form-data发送的真实面目; 3.网络模块移植

mini2440 wince的一些总结

pb生成系统时的一些错误】 首先当你看着FriendlyArm的用户手册来用PB生成自己的WINCE系统或直接用它提供的那个mini2440.pbxml时,会发现提示: One or ...
  • pc102
  • pc102
  • 2013-03-27 14:36
  • 510

SQL Join的一些总结

1.1.1 摘要 Join是关系型数据库系统的重要操作之一,SQL Server中包含的常用Join:内联接、外联接和交叉联接等。如果我们想在两个或以上的表获取其中从一个表中的行与另一个表中的行匹配...

ionic/angular $http post form-data请求

主要有两个步骤,一是重置$http的heads参数,二是参数转换方法$http的heads参数var param = {url:'',method:'post'} //transformRequest...

iOS里实现multipart/form-data格式上传文件

现在是学习笔记,后续会对内容做梳理 Http 请求(后面统一称为报文),包含请求头和请求体两部分,格式如下:POST / HTTP/1.1 Content-Type:application/x-www...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)