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


Answers:


1569

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

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

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

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

(使用HTML表单提交以外的其他方式生成的HTTP请求也可以使用其他编码。JSON是Web服务常用的格式,有些仍然使用SOAP。)

格式的细节对大多数开发人员而言并不重要。要点是:

  • 切勿使用text/plain

在编写客户端代码时:

  • 使用multipart/form-data时,你的形式包括任何<input type="file">元素
  • 否则,您可以使用multipart/form-data或,application/x-www-form-urlencodedapplication/x-www-form-urlencoded会更有效率

在编写服务器端代码时:

  • 使用预先编写的表单处理库

大多数(例如Perl CGI->param或PHP的$_POSTsuperglobal 公开的代码)将为您解决差异。不要费力尝试解析服务器接收的原始输入。

有时您会发现无法同时处理两种格式的库。Node.js最受欢迎的用于处理表单数据的库是body-parser,它不能处理多部分请求(但是有文档建议可以使用的替代方法)。


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

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

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

text/plain是由HTML 5引入的,仅对调试有用-从规范上来说它们不能由计算机可靠地解释 -而且我认为其他与工具结合使用(例如大多数浏览器的开发人员工具中的“网络面板 ”)更好为了那个原因)。


5
@Quentin对不起,如果我们对所有形式使用multipart会出现什么问题?与并删除文件。
Webinan

12
它对于GET表单没有意义,并且使请求的文件大小更大。
昆汀

@Quentin默认将多部分表单数据作为流发送吗?
咆哮者

enctype中的enc代表什么吗?
菲利普·雷哥

1
“ HTML表单提供了ENC odding的三种方法”
Quentin

449

我们什么时候应该使用它

Quentin的答案是正确的:multipart/form-data如果表单包含文件上传,则使用;application/x-www-form-urlencoded否则,如果省略,则使用默认值enctype

我要去:

  • 添加更多HTML5参考
  • 用表单提交示例解释为什么他是对的

HTML5参考

三种可能enctype

如何生成示例

一旦您看到每种方法的示例,就会很清楚它们的工作方式以及何时使用每种方法。

您可以使用以下示例生成示例:

将表单保存到最小.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 62UTF-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

运行我们的小回声服务器:

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

在浏览器中打开HTML,选择文件,然后单击Submit并检查终端。

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 62aωb在UTF-8中)按字面意义发送。您可以使用进行验证nc -l localhost 8000 | hd,其中显示字节:

61 CF 89 62

被发送(61=='a'和62=='b')。

因此很明显:

  • Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150将内容类型设置为,multipart/form-data并说字段由给定的boundary字符串分隔。

    但请注意:

    boundary=---------------------------735323031399963166993862150

    --比实际障碍少两个

    -----------------------------735323031399963166993862150

    这是因为标准要求边界以两个破折号开头--。其他破折号似乎就是Firefox选择实施任意边界的方式。RFC 7578明确提到这两个前划线--是必需的:

    4.1。多部分/表单数据的“边界”参数

    与其他多部分类型一样,这些部分使用边界定界符定界,该定界符使用CRLF,“-”和“ 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-form-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

显然,没有发送文件数据,仅发送了基名。因此,这不能用于文件。

至于文本字段中,我们可以看到,平时打印的字符像ab一个字节被送往,而不可打印的像0xCF,并0x89讨论了3个字节的每个:%CF%89

比较方式

文件上载通常包含许多不可打印的字符(例如图像),而文本形式几乎从来没有。

从示例中我们可以看到:

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

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

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

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


3
@ Khanna111 %CF是3个字节长:%CF:-)使其人类可读的故事。
Ciro Santilli冠状病毒审查六四事件法轮功

6
在OS X上,nc不会同时接受-l-p参数。但是,这对我的作品:while true; do printf '' | nc -l 8000; done
PhilipS

4
没有提到的一个小而重要的要点是,在中指定的边界少了Content-Type两个连字符(--),即,在消息正文中实际使用边界时,必须给它加上前缀--。同样,最后一个边界必须后缀--,但这很容易引起注意。见stackoverflow.com/questions/3508252/...
伯纳德

1
据我所知,将所有DASHES放在边界中的目的是无法通过眼睛检查请求的语法。请不要在您的边界令牌中使用它们。
Dewi Morgan

1
@DewiMorgan您完全正确。我编辑了帖子,并从边界字符串中删除了破折号。
最多

91

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

如果要允许用户通过表单上传文件,则必须使用此enctype


所以..如果文件不是二进制文件,那么没有这个文件我们可以工作吗?
Yugal Jindle 2013年

据我了解,您可以multipart/form-data用来发送非二进制文件,但是效率很低。我相信使用application/x-www-form-urlencoded是发送非二进制数据的正确方法,但是对非二进制文件有更多经验的人可能需要纠正我。
马特·阿斯伯里

11
multipart/form-data用于发送文件的主要优点是它可以在前端和后端自动工作。您无需进行任何特殊处理。所有文件都是二进制文件,即使它们仅包含文本也是如此。 application/x-www-form-urlencoded是不附加文件的POST表单的标准方法。multipart/form-data是发布带有附加文件的表单的标准方法。(还有许多其他编码,例如application/jsonapplication/json-patch+json,它们在服务器和客户端之间的通信中很常见。)
Daniel Luna 2013年

6
值得指出的是,您可以对图像进行base64编码并将其作为纯字符串数据发送。
詹姆斯

3
除了上述@Prospero的注释之外:您绝对可以通过POST发送文件,而无需使用multipart/form-data。您不能做的就是使用没有JavaScript的普通HTML表单提交。设置要使用的表单multipart/form-dataHTML提供的唯一机制,使您无需使用JavaScript即可发布文件。我觉得答案还不够清楚,天真的读者可能会认为无法发送文件而multipart/form-data不是HTTP的局限性;事实并非如此。
Mark Amery

81

提交表单时,您告诉浏览器通过HTTP协议在网络上发送一条消息,该消息已正确封装在TCP / IP协议消息结构中。HTML页面有一种将数据发送到服务器的方式:使用<form>s。

提交表单后,将创建HTTP请求并将其发送到服务器,该消息将包含表单中的字段名称以及用户填写的值。这种传输可以发生POSTGET HTTP方法

  • POST 告诉您的浏览器构建HTTP消息并将所有内容放入消息正文中(这是一种非常有用的处理方式,更加安全且灵活)。
  • GET将在querystring中提交表单数据。它对数据表示和长度有一些限制。

说明如何将表格发送到服务器

属性enctype只有在使用POST方法时才有意义。指定后,它指示浏览器通过以特定方式对内容进行编码来发送表单。从MDN-表单enctype

当method属性的值为post时,enctype是用于将表单提交给服务器的内容的MIME类型。

  • application/x-www-form-urlencoded:这是默认设置。发送表单后,将收集所有名称和值,并对最终字符串执行URL编码
  • multipart/form-data:字符未编码。当表单具有文件上载控件时,这一点很重要。您要发送文件二进制文件,这样可以确保比特流不会改变。
  • text/plain:转换了空格,但不再执行编码。

安全

提交表单时,可能会出现一些安全问题,如RFC 7578第7节:多部分表单数据-安全考虑

所有表单处理软件都应
敏感地对待用户提供的表单数据,因为它通常包含机密
信息或个人识别信息。Web浏览器中广泛使用表单“自动填充”功能。这些可能会被用来诱骗用户
在完成其他
无害的任务时在不知不觉中发送机密信息。multipart / form-data不提供任何
用于检查完整性,确保机密性,避免用户
混淆的功能或其他安全功能;这些问题必须
通过表单填充和表单数据解释应用程序解决。

接收表单并处理表单的应用程序必须小心,不要将数据提供回原本不希望发送的请求表单处理站点。

解释Content-
Disposition标头字段的文件名时,不要无意中覆盖
收件人文件空间中的文件,这一点很重要。

如果您是开发人员,并且服务器将处理用户提交的表单,这些表单最终可能包含敏感信息,则这与您有关。


1
最近一次编辑后有关安全性的内容与操作的问题无关enctype。我知道这实际上是从multipart/form-dataRFC 传来的,但是无论如何,这是关于提交与数据是否按application/x-www-form-urlencoded或正交的正交形式的安全考虑的任意转储multipart/form-data
Mark Amery

38

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


8

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

将enctype的值设置为multipart / form-data,因为数据将分为多个部分,每个文件一个,另加一个可能随它们一起发送的表单主体文本。


这意味着POST通过表单提交文件可能就足够了,并且multipart/form-data以某种模糊的方式添加只是奖金。事实并非如此。大多数文件绝对需要使用multipart/form-data
underscore_d

1
  • enctype(ENC ode TYPE)属性指定将表单数据提交到服务器时应如何编码。
  • multipart / form-data 是enctype属性的值之一,该属性在具有文件上传功能的表单元素中使用。多部分是指表单数据分为多个部分并发送到服务器。

5
我相信enctype不代表加密类型。此级别不涉及加密。我的猜测是编码类型还是封闭类型。但是肯定不是加密类型。
2016年

1
你的最后一颗子弹点这里了解<head><body>无关和混乱。
Mark Amery

0

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


-3

enctype属性指定将表单数据提交到服务器时应如何编码。

仅当method =“ post”时才可以使用enctype属性。

没有字符被编码。当您使用具有文件上载控件的表单时,此值是必需的

W3Schools


2
这句话甚至都没有提到multipart/form-data。还不清楚。“没有编码字符”这句话是什么意思?-1。
Mark Amery
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.