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

一.MINE TYPE问题:

php对mime type为“application/x-www-form-urlencoded”(表单提交)和“multipart/form-data”(文件上传)的Post请求的数据作特殊处理

下面以“multipart/form-data”为例对源码进行解析:

当客户端发起文件提交请求时,Apache会将所接收到的内容转交给mod_php5模块。 当PHP接收到请求后,首先会调用sapi_activate,在此函数中程序会根据请求的方法处理数据,如示例中POST方法,其调用过程如下:


sapi_read_post_data在main/SAPI.c中实现,它会根据POST内容的Content-Type类型来选择处理POST内容的方法:

\

以上代码的关键在于SG(known_post_content_types)变量, 此变更是在SAPI启动时初始化全局变量时被一起初始化的,其基本过程如下:


这里的的php_post_entries定义在main/php_content_types.c文件。如下:


如上所示的MULTIPART_CONTENT_TYPE(multipart/form-data)所对应的rfc1867_post_handler方法就是处理$_FILES的核心函数, 其定义在main/rfc1867.c文件:SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) 后面获取Content-Type的过程就比较简单了:

  • 通过multipart_buffer_eof控制循环,遍历所有的multipart部分
  • 通过multipart_buffer_headers获取multipart部分的头部信息
  • 通过php_mime_get_hdr_value(header, “Content-Type”)获取类型
  • 通过register_http_post_files_variable(lbuf, cd, http_post_files, 0 TSRMLS_CC); 将数据写到$_FILES变量。

main/rfc1867.c


其它的$_FILES中的size、name等字段,其实现过程与type类似。

二.   原生ajax请求不指定MINE TYPE默认都是text/plain(method:POST),chrome调试工具抓包显示:


如果指定 headers: {‘Content-Type’: ‘application/x-www-form-urlencoded’},则显示如下:


 

三.如果post请求MINE TYPE不是application/x-www-form-urlencoded或multipart/form-data,php不作处理,要获取数据只能去读取原生态的输入流php://input

比如用$.ajax方法发送请求时(data参数是一个JSON.stringify()处理后的字符串,而不是一个JSON对象):account_pay_money=0&real_cash_money=80&uid=1191&saveInStore=1&direct_cash=1&projects%5B0%5D%5Bgoods_id%5D=13&projects%5B0%5D%5Bgoods_num%5D=1&projects%5B0%5D%5Bprice%5D=80.00&projects%5B0%5D%5Btech_ids%5D%5B%5D=1029&vt=1441977345904&lsid=1

如果用$.post方法来发送请求(data参数是一个JSON对象,而不要再用JSON.stringify()处理为字符串了)

这个两种数据处理如下:


 

总结:

服务器为什么会对表单提交和文件上传做特殊处理,因为表单提交数据是名值对的方式,且Content-Type为application/x-www-form-urlencoded,而文件上传服务器需要特殊处理,普通的post请求(Content-Type不是application/x-www-form-urlencoded)数据格式不固定,不一定是名值对的方式,所以服务器无法知道具体的处理方式,所以只能通过获取原始数据流的方式来进行解析。

jquery在执行post请求时,会设置Content-Type为application/x-www-form-urlencoded,所以服务器能够正确解析,而使用原生ajax请求时,如果不显示的设置Content-Type,那么默认是text/plain,这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。

没有更多推荐了,返回首页