enctype
,这属性指定了Form的Content-Type,可取的只有application/x-www-form-urlencoded, multipart/form-data, text/plain。
而Content-Type包含3个部分:
- media-type: 资源或数据的 MIME type (必填)
- charset: 字符编码标准
- boundary: 对于多部分实体,boundary 是必需的,其包括来自一组字符的1到70个字符,已知通过电子邮件网关是非常健壮的,而不是以空白结尾。它用于封装消息的多个部分的边界
application/x-www-form-urlencoded 是Form默认的Content-Type:表单提交时编码必须遵循以下标准:
- key和value都会被编码。空格被替换为‘+’,保留字编码对着参照 [RFC1738],非转义字符被替换为‘’%hh‘’的格式(一个%和两个代表示ASCII码的16进制数字),换行被替换为‘%D0%0A’(对应CR LF),都可以通过encodeURI函数转换,详细还请查阅 mdn
- key和value用‘=’来分隔,每一对key和value用‘&’来分隔
比如:
multipart/form-data 是用FormData来传递数据,和上边的区别是,FormData用来传递大数据(非ascii字符和二进制数据),具体请参考另一篇文章 post使用form-data和x-www-form-urlencoded的本质区别 (这篇博客讲的感觉很详细了),编码规则如下:
- 包含一个Content-Disposition字段,值为form-data
- 一个name属行,值为对应表单key的name字段
- 所有的Mime传输一样,用CR LF(‘%0D%0A’)来分隔数据
比如:划线处为规则3
接下我详细说下multipart/form-data编码,假设我们有以下Form
<FORM action="http://server.com/cgi/handle"
enctype="multipart/form-data"
method="post">
<P>
What is your name? <INPUT type="text" name="submit-name"><BR>
What files are you sending? <INPUT type="file" name="files"><BR>
<INPUT type="submit" value="Send"> <INPUT type="reset">
</FORM>
当用户输入‘Larry’在文本input中,还选择了一个文本文件‘file1.txt’,然后点击提交按钮,传向后台的body体为:
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--
http://localhost:8080/api?name=John&age=12
那么在multipart/form-data我们怎么告诉服务器呢,答案就是boundary,有了这个字段,服务器就知道一个value是从哪里开始和到哪里结束,这个字段开发者是不用写的,浏览器会自动加上,网上说我们也可以自行设置,比如你可以设置你喜欢的字符,但是我没有成功,每次都是随机的给分配一个,测试如下:)
回到刚才的Form表单,如果用户选择了第二个文件‘file2.gif’,传输结构会是以下:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--