enctype ='multipart / form-data'是什么意思?
enctype='multipart/form-data'
是什么意思在一个HTML
表单中,我们应该什么时候使用它?
当您发出POST请求时,您必须以某种方式编码形成请求主体的数据。
HTML表单提供了三种编码方法。
-
application/x-www-form-urlencoded
(默认) -
multipart/form-data
-
text/plain
正在做关于添加application/json
,但已经被放弃了。
格式的细节对大多数开发人员来说并不重要。 重要的是:
当你编写客户端代码时,你需要知道的是当你的表单包含任何<input type="file">
元素时,使用multipart/form-data
。
在编写服务器端代码时: 使用预先编写的表单处理库 (例如,Perl的CGI->param
或者PHP的$_POST
superglobal公开的那个),它将为您处理差异。 不要试图parsing服务器收到的原始input。
切勿使用text/plain
。
如果您正在编写(或debugging)一个库来parsing或生成原始数据,那么您需要开始担心格式。 你可能也想知道它的利益。
application/x-www-form-urlencoded
或多或less与URL末尾的查询string相同。
multipart/form-data
要复杂得多,但它允许将整个文件包含在数据中。 结果的一个例子可以在HTML 4规范中find 。
text/plain
是由HTML 5引入的,仅用于debugging – 从规范说起 : 它们不能被计算机可靠地解释 – 而且我认为其他人与工具相结合(如大多数浏览器的开发人员工具中的Net标签)更好)。
我们应该什么时候使用它
Quentin的答案是正确的:如果表单包含file upload,则使用multipart/form-data
否则application/x-www-form-urlencoded
,如果省略enctype
,则是默认值。
我要去:
- 添加更多的HTML5引用
- 用一个表单提交例子来解释他为什么正确
HTML5参考
enctype
有三种可能性 :
-
x-www-urlencoded
-
multipart/form-data
(spec指向RFC2388 ) -
text-plain
。 这是“不可靠的电脑解释”,所以不应该在生产中使用,我们不会再深究。
如何生成示例
一旦你看到每个方法的例子,它就变得很明显,它们是如何工作的,什么时候应该使用每一个方法。
你可以使用下面的例子
-
nc -l
或ECHO服务器 - 一个像浏览器或cURL的用户代理
将表单保存为最小的.html
文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>upload</title> </head> <body> <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> </body> </html>
我们将默认文本值设置aωb
,这意味着aωb
因为ω
是U+03C9
,它们是UTF-8中的字节61 CF 89 62
。
创build要上传的文件:
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
运行我们的小回声服务器:
while true; do printf '' | nc -l 8000 localhost; done
在浏览器中打开HTML,select文件并点击提交并检查terminal。
nc
打印收到的请求。
经testing:Ubuntu 14.04.3, nc
BSD 1.105,Firefox 40。
多部分/格式数据
火狐发送:
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--
对于二进制文件和文本字段,字节61 CF 89 62
(UTF-8中的aωb
)是逐字发送的。 你可以使用nc -l localhost 8000 | hd
来validation nc -l localhost 8000 | hd
,这就是说,字节:
61 CF 89 62
( 61
=='a'和62
=='b')。
所以很清楚:
-
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
将内容types设置为multipart/form-data
并表示字段由给定的boundary
string。 -
每个字段在其数据之前获得一些子标题:
Content-Disposition: form-data;
,字段name
,filename
,后面跟着数据。服务器读取数据直到下一个边界string。 浏览器必须select一个不会出现在任何字段中的边界,所以这就是为什么边界可能因请求而不同。
由于我们有独特的边界,因此不需要编码数据:二进制数据按原样发送。
TODO:什么是最佳的边界大小(
log(N)
我打赌)和algorithm的名字/运行时间find它? 问在: https : //cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences -
Content-Type
由浏览器自动确定。如何确切地被问到: 如何由浏览器确定上传文件的MIMEtypes?
应用程序/ x-WWW窗体-urlencoded
现在将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
很明显,文件数据没有被发送,只有基本名称。 所以这不能用于文件。
至于文本字段,我们看到通常可打印的字符如a
和b
是以一个字节发送的,而不可打印的0xCF
如0xCF
和0x89
分别占用3个字节 : %CF%89
!
对照
file upload通常包含大量不可打印的字符(例如图像),而文本表单几乎从不做。
从我们看到的例子来看:
-
multipart/form-data
:将几个字节的边界开销添加到消息中,并且必须花费一些时间来计算它,但是将每个字节发送到一个字节中。 -
application/x-www-form-urlencoded
:每个字段(&
)有一个单字节边界,但为每个不可打印的字符添加3x的线性开销因子。
因此,即使我们可以用application/x-www-form-urlencoded
发送文件,我们也不想,因为效率太低了。
但是对于在文本字段中find的可打印字符,这并不重要,生成的开销较小,所以我们只是使用它。
在提交表单时,您试图说浏览器通过HTTP协议发送一个正确包含在TCP / IP协议消息结构中的networking消息。 发送数据时,可以使用POST
或GET
方法使用HTTP协议发送数据。 POST
告诉你的浏览器build立一个HTTP消息,并把所有内容放在消息体内(一种非常有用的做事方式,更安全,也更灵活)。 GET
对数据表示和长度有一些限制。
说明你发送的内容
当发送一个文件时,有必要告诉HTTP协议你正在发送一个文件里面有几个特征和信息。 这样就可以一直向接收方发送数据,并让它以当前的格式打开文件,等等。这是来自HTTP协议的要求,如此处所示
您不能使用默认的enctype
参数发送文件,因为您的接收器在阅读时可能会遇到问题(考虑一个文件是特定操作系统的某些数据的描述符,如果您以这种方式看待问题,也许您会明白为什么它如此重要为文件指定不同的enctype
)。
不要忘记安全
这种做事的方式也确保了一些安全algorithm可以处理你的消息。 这些信息也被应用级路由器用来作为外部数据的良好防火墙。
那么,正如你所看到的那样,对于文件使用特定的enctype
并不是一件愚蠢的事情。
enctype='multipart/form-data
是一种允许通过POST发送文件的编码types。 很简单,没有这个编码的文件不能通过POST发送。
如果您希望允许用户通过表单上传文件,则必须使用此enctype 。
enctype='multipart/form-data'
表示不会对字符进行编码。 这就是为什么在将file upload到服务器时使用此types的原因。
因此,当表单需要二进制数据(如文件的内容)上传时,会使用multipart/form-data
将方法属性设置为POST,因为文件内容不能使用表单放入URL参数中。
将enctype的值设置为multipart / form-data,因为数据将被拆分成多个部分,每个文件一个,另外一个用于可能与它们一起发送的表单主体的文本。
通常这是当你有一个POST表单需要把file upload为数据…这将告诉服务器如何编码传输的数据,在这种情况下,它不会被编码,因为它只会传输和上传文件到服务器,例如上传图片或PDF时
- enctype( ENC ode TYPE )属性指定在将表单数据提交给服务器时应如何编码。
- multipart / form-data是enctype属性的值之一,用于具有file upload的表单元素。 多部分手段表单数据分为多个部分发送给服务器。
- 隐喻部分 :一个HTML文档有两个部分 :头部和身体。