背景
CURL在 a.php 中以 POST方式向 b.php 提交數據,但b.php無法接收到數據,而 CURL 操作顯示成功。
原來,"傳遞一個數組到CURLOPT_POSTFIELDS,CURL會把數據編碼成 multipart/form-data,而傳遞一個URL-encoded字符串時,數據會被編碼成 application/x-www-form-urlencoded"。但是在使用 PHP Curl進行Post時可以指定 multipart/form-data 或 application/x-www-form-urlencoded 的方法。
驗證過程
示例:
<?ph $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_exec($ch); curl_close($ch);
這段代碼提交的Content-Type到底是multipart/form-data還是application/x-www-form-urlencoded呢?
tcpdump 抓包, wireshark 分析包內容,發現Content-Type的類型取決於$data的數據類型。
1、如果$data是字符串,則Content-Type是application/x-www-form-urlencoded。
HTML Form URL Encoded: application/x-www-form-urlencoded
Form item: "uname" = "nickname"
Key: uname
Value: nickname
2、如果$data是k=>v的數組,則Content-Type是multipart/form-data,
set boundary
Content-Type: multipart/form-data; boundary=----------------------------749c186646f5\r\n
3、special case:
if pass an array array('uname' => 'nickname', 'uid' => 123456789) to CURLOPT_POSTFIELDS and set the content-type:application/x-www-form-urlencode to CURLOPT_HTTPHEADER
an unexpected result will be happened
[_POST] => Array ( [------------------------------635248b8d641 Content-Disposition:_form-data;_name] => "uname" nickname ------------------------------635248b8d641 Content-Disposition: form-data; name="uid" 123456789 ------------------------------635248b8d641-- )
總結
header 可以設置對 http body data 的編碼方式
CURL_POST:TRUE to do a regular HTTP POST. This POST is the normal application/x-www-form-urlencoded kind, most commonly used by HTML forms.
application/x-www-form-urlencoded form元素默認指定的enctype屬性
multipart/form-data 上傳大量文本,包含非 ASCII字符或者二進制數據。既支持發送文本數據,也支持二進制數據上載。Browser端<form>表單的ENCTYPE屬性值為multipart/form-data,它告訴我們傳輸的數據要用到多媒體傳輸協議,由於多媒體傳輸的都是大量的數據,所以規定上傳文件必須是post方法,<input>的type屬性必須是file。