• 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,这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。

  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/winyh/p/7911204.html
Copyright © 2020-2023  润新知