题 enctype ='multipart / form-data'是什么意思?


是什么 enctype='multipart/form-data' 意思是 HTML 表格以及何时使用?


1024
2017-12-24 12:19


起源




答案:


当您发出POST请求时,您必须以某种方式对构成请求主体的数据进行编码。

HTML表单提供三种编码方法。

  • application/x-www-form-urlencoded (默认)
  • multipart/form-data
  • text/plain

正在进行有关添加的工作 application/json,但这已被放弃。

格式的细节对大多数开发人员来说无关紧要。重点是:

当您编写客户端代码时,您需要知道的是 使用 multipart/form-data 当你的表格包括任何 <input type="file"> 分子

在编写服务器端代码时: 使用预先编写的表单处理库 (例如Perl's CGI->param 或者由PHP公开的那个 $_POST 超级全球)它将为您处理差异。不要费心去解析服务器收到的原始输入。

永远不要用 text/plain


如果您正在编写(或调试)用于解析或生成原始数据的库,那么您需要开始担心格式。您可能还想了解它的利益。

application/x-www-form-urlencoded 与URL末尾的查询字符串大致相同。

multipart/form-data 复杂得多,但它允许整个文件包含在数据中。结果的一个例子可以在 HTML 4规范

text/plain 由HTML 5引入,仅用于调试 - 来自 规范它们无法通过计算机可靠地解释  - 并且我认为其他工具(如大多数浏览器的开发工具中的Net选项卡)与工具相结合更好。


1154
2017-12-24 12:21



@Quentin如果我有一个表格上传文件和 也 具有 textArea。整个表单是否会以二进制(多部分)的形式提交?这是有效的情况吗?或者我应该有多种形式...... - Royi Namir
Multipart不再是任何其他编码的二进制。 Multipart不会阻止您使用非文件输入。拥有多种形式将是愚蠢的。 - Quentin
@Quentin对不起,如果我们对所有表单使用multipart,会出现什么问题?用和发送文件。 - Webinan
它对GET表单没有意义,它使请求的文件大小更大。 - Quentin
@ Quentin ..... [+1]为了获得更好的答案....你能指出一个网络资源....它显示了multipart / form-data的结构......特别是当一个带有图像的字符串时涉及.....谢谢! - Devrath


什么时候应该使用它

昆汀的答案是对的:使用 multipart/form-data 如果表单包含文件上传,和 application/x-www-form-urlencoded 否则,如果省略,这是默认值 enctype

我要去:

  • 添加一些HTML5引用
  • 说明 为什么 他是一个表单提交示例

HTML5参考

三种可能性 对于 enctype

如何生成示例

一旦你看到每个方法的一个例子,就会明白它们是如何工作的,以及何时应该使用每个方法。

您可以使用以下方法生成示

  • 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,这是字节 61 CF 89 62 在UTF-8中。

创建要上传的文件:

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

运行我们的小型echo服务器:

while true; do printf '' | nc -l 8000 localhost; done

在浏览器上打开HTML,选择文件,然后单击“提交”并检查终端。

nc 打印收到的请求。

测试:Ubuntu 14.04.3, ncBSD 1.105,Firefox 40。

多部分/格式数据

Firefox发送:

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 (aωb 在UTF-8中按字面意思发送。您可以通过验证 nc -l localhost 8000 | hd,表示字节:

61 CF 89 62

送了(61 =='a'和 62 =='b')。

因此很明显:

  • Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266 将内容类型设置为 multipart/form-data 并说这些字段是由给定的 boundary 串。

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

    服务器读取数据直到下一个边界字符串。浏览器必须选择不会出现在任何字段中的边界,因此这就是边界可能因请求而异的原因。

    因为我们有唯一的边界,所以不需要对数据进行编码:二进制数据按原样发送。

    TODO:什么是最佳边界尺寸(log(N) 我打赌),以及找到它的算法的名称/运行时间?问: https://cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences

  • Content-Type 由浏览器自动确定。

    具体如何确定被问到: 如何通过浏览器确定上传文件的mime类型?

应用程序/ x-WWW窗体-urlencoded

现在改变了 enctype 至 application/x-www-form-urlencoded,重新加载浏览器,然后重新提交。

Firefox发送:

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 和 0x89 拿起来 3个字节 每: %CF%89

对照

文件上传通常包含许多不可打印的字符(例如图像),而文本形式几乎从不这样做。

从我们看到的例子中可以看到:

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

  • application/x-www-form-urlencoded:每个字段有一个字节边界(&),但增加了一个 线性 开销因素 3X 对于每个不可打印的角色。

因此,即使我们可以发送文件 application/x-www-form-urlencoded,我们不想,因为它是如此低效。

但是对于在文本字段中找到的可打印字符,它无关紧要并且产生的开销较少,因此我们只是使用它。


300
2018-02-07 09:52



好帖子。问题:为什么每个不可打印的字符都有3个字节?例如:对于unicode U + 03C9,我们有%CF%89:这是两个“%”的2个额外字节。我的理解是否正确? - Khanna111
@ Khanna111%CF 是3个字节长: %, C 和 F :-)使人类可读的故事。 - Ciro Santilli 新疆改造中心 六四事件 法轮功
这应该是实际的答案。 - Ramazan Polat
在OS X上, nc 不会同时接受 -l 和 -p 同时争论。但这对我有用: while true; do printf '' | nc -l 8000; done。 - PhilipS
一个小但重要的一点是未提及的是指定的边界 Content-Type 有两个连字符(--)less,即在实际使用消息体中的边界时,必须用它作为前缀 --。此外,最后一个边界必须加上后缀 --,但这很容易引起注意。看到 stackoverflow.com/questions/3508252/... - Bernard


enctype='multipart/form-data 是一种允许通过文件发送文件的编码类型 POST。很简单,没有这种编码就无法发送文件 POST

如果要允许用户通过表单上载文件,则必须使用此方法 ENCTYPE


72
2017-12-24 12:49



那么..如果文件不是二进制文件那么我们可以在没有这个的情况下工作吗? - Yugal Jindle
据我所知,你可以使用 multipart/form-data 用于发送非二进制文件但效率低下。我相信使用 application/x-www-form-urlencoded 是发送非二进制数据的正确方法,但是对非二进制文件有更多经验的人可能需要纠正我。 - Matt Asbury
使用的主要优点 multipart/form-data 发送文件是因为它将在前端和后端自动工作。您无需进行任何特殊处理。所有文件都是二进制文件,即使它们只包含文本。 application/x-www-form-urlencoded 是没有附加文件的POST表单的标准方法。 multipart/form-data 是使用附加文件POST表单的标准方法。 (还有许多其他编码,例如 application/json 和 application/json-patch+json,这对于服务器和客户端之间的通信很常见。) - Daniel Luna
值得指出的是,您可以对图像进行base64编码并将其作为纯字符串数据发送。 - Prospero


提交表单时,您试图说您的浏览器通过HTTP协议发送网络上正确包含在TCP / IP协议消息结构中的消息。发送数据时,您可以使用 POST 要么 GET  方法使用HTTP协议发送数据。 POST 告诉您的浏览器构建一条HTTP消息,并将所有内容放在消息正文中(一种非常有用的方式,更安全,更灵活)。 GET 对数据表示和长度有一些限制。

说明你发送的内容

发送文件时,有必要告诉HTTP协议您发送的文件中包含多个特征和信息。通过这种方式,可以一致地将数据发送到接收器并让它以当前格式打开文件,等等...... 这是HTTP协议的要求,如图所示 这里

您无法使用默认值发送文件 enctype 参数,因为您的接收器可能会遇到读取它的问题(考虑到文件是特定操作系统的某些数据的描述符,如果您以这种方式看到的话,也许您会理解为什么指定不同的这么重要 enctype 对于文件)。

不要忘记安全

这种做法还可以确保某些安全算法可以处理您的消息。应用程序级路由器也使用此信息,以充当外部数据的良好防火墙。

好吧,正如你所看到的,使用特定的东西并不是一件愚蠢的事情 enctype 对于文件。


67
2017-12-24 17:50



邮件或邮件正文的标题? - manikanta
有关enctype的信息是标题的一部分。如果发送文件,http消息的正文是文件的字节流。 - Andry
我同意@manikanta,我很确定POST会在请求正文中发送数据 - Jondlm
大家好!是的,你没事,我前段时间已经修好了答案...... - Andry


enctype='multipart/form-data' 意味着不会编码任何字符。这就是为什么在将文件上传到服务器时使用此类型的原因。
所以 multipart/form-data 当表单需要上传二进制数据(如文件内容)时使用


29
2017-07-04 09:13





将method属性设置为POST,因为无法使用表单将文件内容放在URL参数中。

将enctype的值设置为multipart / form-data,因为数据将被拆分为多个部分,每个文件一个,另外一个用于可以与它们一起发送的表单主体的文本。


9
2017-09-25 11:53



这意味着 POST 可能足以通过表单提交文件并添加 multipart/form-data 只是一些模糊的奖励。事实并非如此。大多数文件绝对需要使用 multipart/form-data。 - underscore_d


  • ENCTYPE(ENC类型)attribute指定在将表单数据提交给服务器时应如何编码表单数据。
  • 多部分/格式数据  是enctype属性的值之一,用于具有文件上载的表单元素。 多部分 表示形式数据分为 多个部分 并发送到服务器。
    • 隐喻 部分 :HTML文档有 两部分:头部和身体。

1
2017-12-27 01:29



我相信 ENCTYPE 不代表加密类型。此级别不涉及加密。我的猜测是编码类型或封闭类型。但肯定不是加密类型。 - Yeo


通常这是当你有一个POST表单,需要将文件上传作为数据...这将告诉服务器它将如何编码传输的数据,在这种情况下,它将不会被编码,因为它只会传输和上传文件到服务器,例如上传图像或pdf时


0
2018-03-10 09:29