表單提交時編碼類型enctype詳解
很早以前,當還沒有前端這個概念的時候,我在寫表單提交完全不去理會表單數據的編碼,在action
屬性裏寫好目標URL,剩下的啊交給瀏覽器吧~但是現在,更多時候我們都采用Ajax方式提交數據,這種原始的方式僅僅被當成優雅降級的產物。
當我們用異步方式提交表單,就需要稍微關註一下表單數據的編碼問題了。回想一下,在寫回調函數時是不是有根據過請求的Content-Type
寫不同業務邏輯的經歷,那這個Content-Type
和表單的編碼有什麽聯系嗎?有沒有在明明前端已經發數據給後端了,後端的小夥伴死活取不到數據的情況?這些糾結的問題背後的原因真是困擾了我好久,今天在篇文章裏就要把它們掰扯清楚!
是什麽決定了表單的編碼?
熟悉表單元素<form>
的小夥伴,對其中的屬性enctype
一定不會陌生,就是它規定了對表單提交給服務器時表單數據編碼的內容類型(Content Type)。以下引用,摘自HTML 4.01規範的Form章節:
enctype = content-type [CI]
This attribute specifies the content type used to submit the form to the server
content type?這不就是我們在回調函數裏判斷返回數據的類型,並且是在請求頭中的那個玩意兒嗎?!沒錯!就是它!根據HTML 4.01規範的基礎數據類型的說明,這個content type指定了連接資源的屬性
表單編碼類型
知道了表單編碼由enctype
決定的,那麽它究竟有多少可選的取值呢?是不是所有的MIME類型它都能用呢?
實際上,根據HTML5 規範中所敘述的,enctype
具有以下三種選項,其中最後一項text/plain
是相比4.01新增的。
-
application/x-www-form-urlencoded
-
multipart/form-data
-
text/plain
application/x-www-form-urlencoded
這是默認的編碼類型,使用該類型時,會將表單數據中非字母數字的字符轉換成轉義字符,如"%HH",然後組合成這種形式key1=value1&key2=value2
註意:
-
若表單中有文件,則只留文件名;
multipart/form-data
該類型用於高效傳輸文件、非ASCII數據和二進制數據,將表單數據逐項地分成不同的部分,用指定的分割符分割每一部分。每一部分都擁有Content-Disposition
頭部,指定了該表單項的鍵名和一些其他信息;並且每一部分都有可選的Content-Type
,不特殊指定就為text/plain
。下面給出一個采用multipart/form-data
編碼類型的例子:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
註意:
-
一般來說,
method
和enctype
是兩個不同的互不影響的屬性,但在傳文件時,method
必須要指定為POST
,否則文件只剩下filename了; -
當沒有傳文件時,
enctype
會改回默認的application/x-www-form-urlencoded
。
text/plain
按照鍵值對排列表單數據key1=value1\r\nkey2=value2
,不進行轉義。
註意:
-
若表單中有文件,則只留文件名;
application/json及其他MIME類型
另外,還需要說明表單數據編碼類型application/json
,已經被W3C遺棄(詳見HTML JSON Form Submission),建議不要在<form enctype="...">
中使用了,即使用了如果瀏覽器不支持,也會替換成application/x-www-form-urlencoded
。
同理,其余的MIME類型,也不支持,均會替換成默認編碼application/x-www-form-urlencoded
。
PS:貌似現在瀏覽器都不支持了,我先用了下面幾個瀏覽器:
-
FF43:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0
-
Chrome49, Safari9.1:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
-
IE6, 8
後記
所以,enctype
可以認為就是表單數據的content type(MIME type)
,只不過其取值不能用除了上面提到的三個,否則會轉換成默認的編碼。
今天掰扯完了表單提交時的編碼類型enctype
,以及它和content type
、MIME type
的關系。下次再總結一下Ajax提交表單的類型吧。
表單提交時編碼類型enctype詳解