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表单提交的,代码如下:   ...

HTTP协议之multipart/form-data请求分析

首先来了解什么是multipart/form-data请求: 根据http/1.1 rfc 2616的协议规定,我们的请求方式只有OPTIONS、GET、HEAD、POST、PUT、DELETE、T...
  • five3
  • five3
  • 2012年01月06日 15:36
  • 169893

使用FormData对象提交表单及上传图片

FormData 对象,可以把form中所有表单元素的name与value组成一个queryString,提交到后台。在使用Ajax提交时,使用FormData对象可以减少拼接queryString的...
  • fdipzone
  • fdipzone
  • 2014年08月29日 00:25
  • 126018

c# 模拟表单提交,post form 上传文件、大数据内容

表单提交协议规定: 要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数, 这个参数是由应用程序自行产生,它会用...
  • xxj_jing
  • xxj_jing
  • 2015年12月08日 16:54
  • 11833

python拼接form-data的post内容

#!\urs\bin\env python #encoding:utf-8 #设置编码方式 from http2 import http import urllib def R...
  • five3
  • five3
  • 2013年04月26日 18:42
  • 6111

AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式

HTTP请求中,如果是get请求,那么表单参数以name=value&name1=value1的形式附到url的后面,如果是post请求,那么表单参数是在请求体中,也是以name=value&name...
  • mhmyqn
  • mhmyqn
  • 2014年05月11日 21:20
  • 130706

HTTP中header的信息讲解以及设置

HTTP消息中header头部信息的讲解 本文导读:HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和可选的...
  • theowl
  • theowl
  • 2015年08月03日 09:07
  • 19633

post表单时的html报文的header信息

表单只有text的时候 POST /example.php HTTP/1.1Host: 127.0.0.1User-Agent: PEAR HTTP_Request class ( http://pe...
  • hahawen
  • hahawen
  • 2004年05月07日 17:11
  • 7894

postman中 form-data、x-www-form-urlencoded、raw、binary的区别

form-data:                     就是multipart/form-data,将表单内要上传的数据,处理为一条消息,以标签为单元,一个个的隔开。既可以上传键值对,也可以上传...

form表单-request得不到值为null-以及Enctype=multipart/form-data介绍

form表单-request得不到值为null-以及Enctype=multipart/form-data介绍
  • NJUPT_T
  • NJUPT_T
  • 2016年01月22日 15:25
  • 3600
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POST发送form-data的一些总结
举报原因:
原因补充:

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