HTML <form< 標籤的 enctype 屬性
首先來瞭解什麼是 <form< 標籤的 enctype 屬性,enctype 屬性規定了在發送到伺服器之前應該如何對錶單資料進行編碼,有三種類型:
屬性值 描述
application/x-www-form-urlencoded 預設模式,在發送到伺服器之前,所有字元都會進行編碼(空格轉換為 “+” 加號,特殊符號轉換為 ASCII HEX 值)
multipart/form-data 不對字元編碼,在使用包含檔案上傳控制項的表單時,必須使用該值。
text/plain 空格轉換為 “+” 加號,但不對特殊字元編碼。
當在網頁提交了一個表單之後,可以使用三種 PHP 方式來擷取 Post 資料:$_POST,$HTTP_RAW_POST_DATA,and php://input,有什麼區別呢?
$_POST
$_POST 是擷取表單 POST 過來資料(body部分)的最常用方法,上傳的檔案資訊使用 $_FILES 擷取。
$HTTP_RAW_POST_DATA
當瀏覽器從表單發送 POST 請求的時候,預設的 media type 是 “application/x-www-form-urlencoded”,意思就是欄位名和值都編碼了,每個 key-value 對使用 ‘&’ 字元分隔開,key 和 value 使用 ‘=’ 分開,並且 key 和 value 中的空格都會被替換成 + ,其他特殊字元都會被使用 urlencode 方式進行編碼。
比如下面的 key-value 對:
name: Jonathan Doe
age: 23
formula: a + b == 13%!
會被編碼下面的未經處理資料:
name=Jonathan+Doe&age=23&formula=a+%2B+b+%3D%3D+13%25%21
PHP 會解析這些原始的 POST 資料,並且格式化成數組,填充到 $_POST 中:
Array
(
[name] => Jonathan Doe
[age] => 23
[formula] => a + b == 13%!
)
$HTTP_RAW_POST_DATA 是 PHP 的一個預定義的變數,用來擷取原始的 POST 資料,比如上面的情況下,$HTTP_RAW_POST_DATA 的值就是:
name=Jonathan+Doe&age=23&formula=a+%2B+b+%3D%3D+13%25%21
但是 $HTTP_RAW_POST_DATA 需要在 php.ini 中設定開啟:
always_populate_raw_post_data = On
還有一點,$HTTP_RAW_POST_DATA 不支援 enctype=”multipart/form-data” 方式傳遞的資料,這種情況下,我們要用 $_POST 擷取欄位的內容,$_FILES 來擷取上傳的檔案資訊。
php://input
由於 $HTTP_RAW_POST_DATA 取決於 pho.ini 設定,有沒有更好的方法呢?
我們可以使用 php://input 來擷取原始的 POST 資料,並且 php://input 比 $HTTP_RAW_POST_DATA 更少消耗記憶體,當然 php://input 和 $HTTP_RAW_POST_DATA 一樣,它也不支援 enctype=”multipart/form-data” 方式傳遞的資料。
由於 php://input 只是資料流,我們可以使用 file_get_contents() 函數去擷取它的內容:
$post_data = file_get_contents('php://input');
print_r($post_data);
擷取到的內容和 $HTTP_RAW_POST_DATA 是一樣的。
原始的 POST 資料有什麼用?
那麼原始的 POST 資料有什麼用?因為很多時候,接收到不是網頁 POST 過來的資料,而是可能通過其他方式 POST 過來的 “text/xml” 格式的資料,這些內容無法解析成 $_POST 數組,這個時候我們就需要原始的 POST 資料進行處理。