<form>
中的 enctype
属性决定了请求头中的 Content-Type
,这是服务器判断数据格式的依据,非常重要。
application/x-www-form-urlencoded
enctype
属性的默认值为 application/x-www-form-urlencoded
,意思是:这是采用URL Encoding编码的表单数据。
URL Encoding
URL Encoding 也称作百分号编码,是一种将数据转换成ASCII字符的编码方式。
例如ω (U+03C9)会被编码成 %CF%89
,可以看出,对于非ASCII码,URL编码的效率较低。前面ω这个例子,utf-8编码只需要两个字节,但URL编码却需要6个字节, 空间消耗是前者的三倍。
所以我们在表单里多用ASCII字符作为value上传是有好处的。
multipart/form-data
如果要上传文件,则必须将 enctype
设置为 multipart/form-data
。这样,文件数据会被分割成多个部分,每个文件单独占用一个部分。
案例
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
三个文件构造如下:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
对应的发送数据如下:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
可以看出,用 multipart/form-data
之后,数据被分割成多个部分,并用分隔符隔开。每个文件部分有自己的子头,子头上有文件名和字段名称,还有一个浏览器自动推测出来的 Content-Type
。
可见, multipart/form-data
会增加一些 boundary 的字节空间开销,同时需要计算每一部分的大小和类型,增加时间开销。
如果此时,将 enctype
设置为 application/x-www-form-urlencoded
,那么对应的发送数据变为
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
可以看出,此时表单只上传了文件名称,并没有实际文件的数据。
结论
multipart/form-data
对于非ASCII字符,数据编码方式效率高,适合传输文件。
application/x-www-form-urlencoded
对于少量文本字符,overhead不像multipart/form-data
那么高,适合传输不含文件的表单数据。
网友评论