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&#x03C9;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&#x03C9;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并表示字段由给定的boundarystring。

  • 每个字段在其数据之前获得一些子标题: Content-Disposition: form-data; ,字段namefilename ,后面跟着数据。

    服务器读取数据直到下一个边界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 

很明显,文件数据没有被发送,只有基本名称。 所以这不能用于文件。

至于文本字段,我们看到通常可打印的字符如ab是以一个字节发送的,而不可打印的0xCF0xCF0x89分别占用3个字节%CF%89

对照

file upload通常包含大量不可打印的字符(例如图像),而文本表单几乎从不做。

从我们看到的例子来看:

  • multipart/form-data :将几个字节的边界开销添加到消息中,并且必须花费一些时间来计算它,但是将每个字节发送到一个字节中。

  • application/x-www-form-urlencoded :每个字段( & )有一个单字节边界,但为每个不可打印的字符添加3x线性开销因子。

因此,即使我们可以用application/x-www-form-urlencoded发送文件,我们也不想,因为效率太低了。

但是对于在文本字段中find的可打印字符,这并不重要,生成的开销较小,所以我们只是使用它。

在提交表单时,您试图说浏览器通过HTTP协议发送一个正确包含在TCP / IP协议消息结构中的networking消息。 发送数据时,可以使用POSTGET 方法使用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文档有两个部分 :头部和身体。