首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 輸入流 php://input 深度解析:POST 原始數據讀取、XML-RPC 實踐與陷阱避坑

     編輯:PHP 相關知識

php://input 是 PHP 提供的唯讀流,用於讀取 未經解析的原始 HTTP 請求體。它在 XML-RPC、REST API、Webhook 接收、非標準 Content-Type 處理等場景不可或缺。本文通過抓包實驗,系統對比 $_POST、$HTTP_RAW_POST_DATA、php://input 三者異同,揭示核心規則與常見誤區。

核心結論速覽

場景Content-Type$_POSTphp://input$HTTP_RAW_POST_DATA
普通表單提交application/x-www-form-urlencoded✅ 解析後數組✅ 原始字符串✅ 需開啟 always_populate_raw_post_data
JSON/XML APIapplication/json, text/xml❌ 空數組✅ 原始字符串✅ 同上
文件上傳multipart/form-data✅ 解析後數組(不含文件)❌ 空字符串❌ 空
GET 請求無 Body❌❌ 空❌ 空

一、三大數據源的底層邏輯

  1. $_POST:PHP 僅在 Content-Type: application/x-www-form-urlencoded 或 multipart/form-data 時自動解析填充,且經過 urldecode()。
  2. php://input:只要 Content-Type ≠ multipart/form-data,直接讀取長度為 Content-Length 的請求體原始字節,不解析、不解碼,內存效率高,無需 php.ini 配置。
  3. $HTTP_RAW_POST_DATA:PHP 無法識別 Content-Type 時的備選填充,需 always_populate_raw_post_data = On,同樣不支持 multipart/form-data,PHP 7.0 已移除。

二、實驗驗證:抓包看本質

測試腳本 phpinput_server.php 同時輸出三者:

<?php
$raw = file_get_contents('php://input', 'r');
echo "-------\$_POST------------------\n"; var_dump($_POST);
echo "-------php://input-------------\n"; echo $raw . "\n";
?>

1. 標準表單 POST (application/x-www-form-urlencoded)

HTTP 請求體: n=perfgeeks&p=7788
$_POST:     array('n'=>'perfgeeks','p'=>'7788')
php://input: n=perfgeeks&p=7788  ← 內容一致,格式不同

2. XML-RPC POST (text/xml)

HTTP 請求體: jt_userinfo
$_POST:     array(0) {}  ← 空!
php://input: 完整 XML 字符串  ← 唯一可用數據源

3. 文件上傳 (multipart/form-data)

HTTP 請求體: 包含 boundary 分隔的多部分數據
$_POST:     array('n'=>'perfgeeks')  ← 僅普通字段
php://input: 空字符串  ← PHP 刻意屏蔽

4. GET 請求

HTTP 請求體: (空)
php://input: 空  ← GET 數據在 URL Query String,不在 Body

三、關鍵規則總結

  1. Content-Type = application/x-www-form-urlencoded 且 POST 時,$_POST 與 php://input 內容等價(前者解碼後數組,後者原始字符串)。
  2. php://input **無法讀取** multipart/form-data,**無法讀取** GET 查詢字符串。
  3. php://input 與 $HTTP_RAW_POST_DATA 內容始終一致,但前者無需配置、內存效率更高、PHP 7+ 推薦唯一選擇。
  4. $_GET 數據來自 URL Path 中的 Query String,與請求體無關。

四、實戰最佳實踐

<?php
// 通用原始數據讀取器
function getRawInput() {
    // PHP 5.6+ 可直接用 php://input
    // 兼容舊版本:優先 php://input,回退 $HTTP_RAW_POST_DATA
    $raw = file_get_contents('php://input');
    if ($raw === '' && isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
        $raw = $GLOBALS['HTTP_RAW_POST_DATA'];
    }
    return $raw;
}

// JSON API 典型用法
$raw = getRawInput();
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    exit('Invalid JSON');
}
// 業務邏輯...
?>

五、常見坑位與對策

坑位現象原因對策
文件上傳 php://input 為空無法獲取上傳數據PHP 刻意屏蔽 multipart/form-data用 $_FILES 處理文件,$_POST 處理字段
重複讀取 php://input第二次讀取為空流不可重風讀取後存變量復用,或用 tmpfile 緩存
大請求體內存暴漲OOM一次性讀入內存分塊讀取 fopen('php://input','r') + fread 循環
Content-Length 缺失讀取截斷/掛起Chunked Transfer Encoding確保客戶端發送 Content-Length 或升級 PHP 7.1+ 支持 chunked

徹底理解 php://input 的適用邊界,是構建健壯 API 接口、Webhook 接收端、非標準協議適配器的前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved