几种content-type提交以及$_POST 和php://input
在表单提交数据时,需要告诉服务端自己的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