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,這時服務器就不知道怎么解析數據了,所以才只能通過獲取原始數據流的方式來進行解析請求數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM