PHP的"php://input"和$HTTP_RAW_POST_DATA 和$_POST的關係

最近一直在寫接口,順便把 php 輸入輸出流相關知識點學習了一遍php

理論知識

php://input 

php://input 數據輸入流存放着 post 請求發送過來的原生數據,但 Content-Type:multipart/form-data(上傳文件或圖片的表單)的數據則不會載入其中,其餘類型:html

application/x-www-form-urlencode    foo1=bar1&foo2=bar2 普通的表單數據json

application/json   {"foo1":"bar1", "foo2":"bar2",}數組

application/xml   <xml version="1.0"><data><foo1>bar1</foo1><foo2>bar2</foo2></data>服務器

都會被載入其中app

$HTTP_RAW_POST_DATA

$HTTP_RAW_POST_DATA 中的內容與 php://input 並沒有區別,一樣沒法識別 curl

Content-Type:multipart/form-data 的請求數據,且默認狀況下它與 $_POST 互斥,即若請求數據格式能夠填充至 $_POST 中去,即使它也能識別,也不會填充數據,好比 application/x-www-form-urlencode 類型的請求數據, php://input $_POST 和 它都能識別,但 $_POST 填充後默認配置下它是不會被填充的,除非修改 php.ini 文件將  always_populate_raw_post_data 配置參數使能,即只要能識別,就填充,無論 $_POST 是否被填充ide

$_POST

php 能自動識別處理填充到 $_POST 數組中的只有:post

application/x-www-form-urlencode    不含有文件的表單性能

multipart/form-data   含有文件的表單(此時 php://input 和 $HTTP_RAW_POST_DATA 是沒法識別數據流的

兩種php的標準數據類型


客戶端的GET/POST的本質區別

GET 不包含數據流

GET請求並不像POST請求會有 form body 數據,GET請求的全部信息都包含在了請求的header中 query string 中,經過url進行傳遞,說白了它所表明的是一個標識而不含有數據流,因此PHP並不會把 GET 請求裝入數據流中,而只是簡單的將其解析填充到$_GET數組當中

請求頭:

GET url HTTP/1.1

Accept:期待服務器返回什麼格式的數據 text/html application/json application/xml image/jpeg video/mp4 等等


POST 含有數據流

POST請求包括header和from body,header頭指明請求的url,form body 中存放數據提交給服務端,PHP 會根據提交的數據類型動態的將數據流轉化爲相應的模式,好比一下兩種PHP能識別處理POST請求的數據類型

Content-Type:application/x-www-form-urlencoded //普通的表單
Content-Type:multipart/form-data //encrypt mutiple/form-data

=====================================================================

=====================================================================

其實你會發現普通的表單提交 from data 所攜帶的數據編碼同 get 請求中的 query string 徹底同樣,但這也是他們的本質區別, get 並不攜帶數據流 ,它徹底整合到 header 流中去,php 將其填充到 $_GET 數組中 , $_POST 數組中則是能被 PHP 識別並處理的 請求中的 from body (呃,就是 from data)中的數據

=====================================================================

=====================================================================

服務器端對POST請求的處理

PHP能識別並處理的POST請求的數據類型只有

application/x-www-form-urlencode

multipart/form-data

注意是識別並處理,將 POST 過來的數據識別處理填充到全局 $_POST 數組中去,其餘類型的數據則沒法填充 $_POST 數組

但在工做中咱們不可能一直用表單請求服務器,APP開發時請求服務端每每發送的是 applicantion/json 或 applicant/xml 類型的參數數據,這時 PHP 沒法識別處理此類數據流,但 PHP 會將此數據流存放在 php://input 數據流中


php://input 數據流

php://input 數據流存放的內容和 $HTTP_RAW_POST_DATA 的內容徹底同樣 但牽扯到性能方面的問題咱們這裏不推薦使用 $HTTP_RAW_POST_DATA  你能夠認爲 php://input 是一個資源

$input_stream = file_get_contents("php://input");

這樣就獲取到了此數據流中的內容


實例

   服務器端

<?php
$input_stream =file_get_contents("php://input");
echo "==============this is php://input data===============\n";
echo $input_stream . "\n";
echo "==============this is post array data===============\n";
echo var_export($_POST, true);
?>

  application/x-www-form-urlencoded post請求

curl -H "Content-Type:application/x-www-form-urlencoded" -X POST -d 'name=sallency&age=25' -o data.txt http://192.168.30.50:8082/curl.php

//result
==============this is php://input data===============
name=sallency&age=25
==============this is post data===================
array (
  'name' => 'sallency',
  'age' => '25',
)

   application/json post請求

curl -H "Content-Type:application/json" -X POST --data '{"name":"sallency", "age":"25"}' -o data.txt http://192.168.30.50:8082/curl.php

//result
==============this is php://input data===============
{"name":"sallency", "age":"25"}
==============this is post data===================
array (
)

   application/xml post請求

curl -H "Content-Type:application/xml" -X POST -d '<?xml version="1.0" encoding="utf-8"?><user><name>sallency</name><age>25</age></user>' -o data.txt 

//result
<?xml version="1.0" encoding="utf-8"?><user><name>sallency</name><age>25</age></user>
==============this is post data===================
array (
)

因爲模擬mutipart/form-data的表單提交比較複雜咱們這裏就不作模擬了

總結:

一、php 能識別處理的標準數據類型爲:application/x-www-form-urlencoded(普通的表單) 和 mutipart/form-data(encrypt="mutipart/form-data" 的表單),其餘的好比 application/json application/xml 是沒有辦法處理好填充到 $_POST 中去的,但它們會被填充到 php://input 流中(所謂處理是 php 自動解析好給你 拿來就用的意思 注意我文章中屢次提到識別和處理 )

二、php://input 能識別處理 mutipart/form-data 外的全部類型的數據,將其填充到本身的數據流, 咱們能夠經過它獲取數據手動解析

=====================================================================

這些爲數據流資源符

php://input php://output 
php://stdin php://stdout php://stderr

CLI下

STDIN = $stdin = fopen("php://stdin", "r") 是同樣的 標準輸入的句柄
STDOUT = $stdout = fopen("php://stdout", 'w')
STDERR = $stderr = fopen("php://stderr", 'w')

fread(STDIN, 1024)
fgets(STDIN)
while ($line = fgets(STDIN)) {
    echo $line;
}
fwrite(STDOUT, "hello world!")
file_get_contents("php://stdin")
file_put_contents("php://stdout", "hello world!")

STDIN STDOUT STDERR 爲句柄 能夠直接被fread fwrite fgets使用
file_get_contents()/file_put_contents()打開或寫入的是資源而不是資源句柄
相關文章
相關標籤/搜索