在表單提交數據時,需要告訴服務端自己的content-type,好讓服務端處理。
默認表單提交是x-www-form-urlencoded,還有一種常見的 multipart/form-data。那這倆的區別是啥呢?
在postman工具中,很容易看出來二者的區別。
x-www-form-urlencoded:
查看http請求:
POST /hi.php HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded Cache-Control: no-cache Postman-Token: a1054dd4-5f58-038c-6082-326721c85a7a id=1%2B1&val=44753
在 x-www-form-urlencoded中,body體中是key=value&key=xx形式,並且是urlencode后的。
multipart/form-data:
查看http請求:
POST /hi.php HTTP/1.1 Host: localhost Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW Cache-Control: no-cache Postman-Token: dddb1f15-348b-5e3f-244c-aa0d8680bd3d ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="id" 1+1 ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="val" 44753 ------WebKitFormBoundary7MA4YWxkTrZu0gW--
form-data中含有boundary=----***
常見的content-type還有一種json形式:
Content-Type: application/json
查看http請求:
POST /hi.php HTTP/1.1
Host: localhost
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 38f8844e-bd9f-a892-5107-a3f4e6b81a41
{"a":"xx"}
再看下$_POST和php://input的區別聯系
利用一段測試代碼:
<?php $arr = $_POST; $raw_post_data = file_get_contents('php://input', 'r'); file_put_contents('hsd.log', "\$_POST\r\n".print_r($arr,true)."\r\n", FILE_APPEND); file_put_contents('hsd.log', "php://input\r\n".print_r($raw_post_data,true)."\r\n", FILE_APPEND); file_put_contents('hsd.log', "content_type: ".print_r($_SERVER['HTTP_CONTENT_TYPE'],true)."\r\n", FILE_APPEND); file_put_contents('hsd.log', print_r("====================",true)."\r\n", FILE_APPEND);
在幾種content-type表現如下:(php version 5.5.3)
1. 當是x-www-form-urlencoded時,
$_POST Array ( [id] => 1+1 [val] => 44753 ) php://input id=1%2B1&val=44753 content_type: application/x-www-form-urlencoded
php://input中的形式和body體中是一樣的,同樣是urlencode過的。
2. 當是 multipart/form-data時,
$_POST
Array
(
[id] => 1+111
[val] => 44753
)
php://input
content_type: multipart/form-data; boundary=----WebKitFormBoundaryUUacTtaG65hX7g6y
發現$_POST依然可以獲取到參數。此時php://input 獲取不到值。
(測試在hhvm HipHop VM 3.0.1;baidu version:1.0.6.4 php://input可以獲取到multipart/form-data 提交參數)如下:
$_POST
Array
(
[id] => 1+111
[val] => 44753
)
php://input
------WebKitFormBoundaryxHArWQUlukzFfZAb
Content-Disposition: form-data; name="id"
1+111
------WebKitFormBoundaryxHArWQUlukzFfZAb
Content-Disposition: form-data; name="val"
44753
------WebKitFormBoundaryxHArWQUlukzFfZAb--
content_type: multipart/form-data; boundary=----WebKitFormBoundaryxHArWQUlukzFfZAb
3. 當是application/json時,
$_POST
Array
(
)
php://input
{"a":"xx"}
content_type: application/json
此時,$_POST獲取不到提交參數。php://input 可以獲取到。這種json提交數據,php接收參數需要使用 file_get_contents('php://input', 'r')。
總結:
$_POST只能獲取到form提交的數據,而php://input獲取不到 multipart/form-data提交的數據。
這里順便提下,如何提交給php獲取$_POST的key=>value是數組形式。
$arrParams = array( 'person[0][first_name]' => 1, 'person[0][last_name]' => 1, 'person[1][first_name]' => 111, 'person[1][last_name]' => 222, );
這樣$_POST['person'] 就是個二維數組了。
$_POST Array ( [person] => Array ( [0] => Array ( [first_name] => a [last_name] => b ) [1] => Array ( [last_name] => d ) ) ) php://input person%5B0%5D%5Bfirst_name%5D=a&person%5B0%5D%5Blast_name%5D=b&person%5B1%5D%5Blast_name%5D=c&person%5B1%5D%5Blast_name%5D=d content_type: application/x-www-form-urlencoded