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

EBA*_*BAG 1290 html multipartform-data http-headers

enctype='multipart/form-data'HTML表单中的含义是什么?我们何时应该使用它?

Que*_*tin 1453

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

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

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

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

(使用除HTML表单提交之外的其他方式生成的HTTP请求,可以进行其他编码.)

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

  • 切勿使用text/plain.

在编写客户端代码时:

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

在编写服务器端代码时:

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

大多数(例如Perl CGI->param或PHP的$_POST超全局公开的那个)将为您处理差异.不要费心去解析服务器收到的原始输入.

有时你会发现一个无法处理这两种格式的库.Node.js用于处理表单数据的最流行的库是body-parser,它不能处理多部分请求(但是有文档推荐一些替代方案可以).


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

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

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

text/plain由HTML 5引入,仅用于调试 - 来自规范:它们不能被计算机可靠地解释 - 我认为其他工具(如大多数浏览器的开发工具中的Net选项卡)更好为了那个原因).

  • 它对GET表单没有意义,它使请求的文件大小更大. (10认同)
  • @Quentin对不起,如果我们对所有表单都使用multipart会有什么问题?用和发送文件. (5认同)
  • 因为它有多个部分 (5认同)
  • “HTML 表单提供了三种 **ENC**oding 方法” (3认同)
  • @MasterJoe因为它可以有多个由边界分隔的数据项,请参阅[RFC 2046第5.1.1节](https://tools.ietf.org/html/rfc2046#section-5.1.1)。 (2认同)

Cir*_*四事件 404

什么时候应该使用它

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>
Run Code Online (Sandbox Code Playgroud)

我们将默认文本值设置为a&#x03C9;b,这意味着a?b因为?是UTF-8 U+03C9中的字节61 CF 89 62.

创建要上传的文件:

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
Run Code Online (Sandbox Code Playgroud)

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

while true; do printf '' | nc -l 8000 localhost; done
Run Code Online (Sandbox Code Playgroud)

在浏览器上打开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--
Run Code Online (Sandbox Code Playgroud)

对于二进制文件和文本字段,字面61 CF 89 62(a?b以UTF-8为单位)按字面发送.您可以验证,nc -l localhost 8000 | hd表示字节:

61 CF 89 62
Run Code Online (Sandbox Code Playgroud)

被发送(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

现在更改enctypeapplication/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
Run Code Online (Sandbox Code Playgroud)

显然,文件数据没有发送,只有基本名称.所以这不能用于文件.

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

对照

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

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

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

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

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

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

  • 在OS X上,`nc`不会同时接受`-l`和`-p`参数.但这对我有用:"虽然真实; 做printf''| nc -l 8000; done`. (6认同)
  • 一个小但重要的一点是没有提到的是`Content-Type`中指定的边界有两个连字符(` - `)较少,即当实际使用消息体中的边界时,你必须在它前面加上` --`.此外,最后一个边界必须以" - "为后缀,但这很容易引起注意.请参阅/sf/ask/245577671/ (4认同)
  • @ Khanna111`%CF`长3个字节:`%`,`C`和`F` :-)使人类可读的故事. (3认同)

Mat*_*ury 85

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

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

  • 使用`multipart/form-data`发送文件的主要优点是它可以在前端和后端自动工作.您无需进行任何特殊处理.所有文件都是二进制文件,即使它们只包含文本.`application/x-www-form-urlencoded`是POST表单没有附加文件的标准方法.`multipart/form-data`是使用附件发布表单的标准方法.(还有许多其他编码,例如`application/json`和`application/json-patch + json`,这些编码对于服务器和客户端之间的通信很常见.) (10认同)
  • 值得指出的是,您可以对图像进行base64编码并将其作为纯字符串数据发送. (5认同)
  • 除了上面@Prospero的注释之外:您绝对可以通过POST发送文件,而无需使用`multipart / form-data`。您不能*做的是使用没有JavaScript的普通HTML表单提交来完成。设置表单使用`multipart / form-data`是* HTML *提供的唯一机制,使您无需使用JavaScript即可发布文件。我觉得答案还不够清楚,天真的读者可能会认为无法发送没有`multipart / form-data`的文件是* HTTP *的局限性;事实并非如此。 (2认同)

And*_*dry 73

提交表单时,您告诉浏览器通过HTTP协议发送网络上的消息,该消息正确地包含在TCP/IP协议消息结构中.HTML页面有一种向服务器发送数据的方法:使用<form>s.

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

  • POST 告诉您的浏览器构建一条HTTP消息并将所有内容放在消息正文中(一种非常有用的方式,更安全,更灵活).
  • GET将在查询字符串中提交表单数据.它对数据表示和长度有一些限制.

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

属性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头字段的文件名时,重要的是不要无意中覆盖
收件人文件空间中的文件.

如果您是开发人员,并且您的服务器将处理用户提交的表单(可能最终包含敏感信息),则会引起您的注意.

  • 最近编辑后有关安全性的内容与 `enctype` 的作用无关。我知道它字面上来自`multipart/form-data` RFC,但尽管如此,它是关于提交表单的安全考虑的任意转储,这些表单与数据是作为`application/x-www-form-urlencoded` 还是作为发送完全正交多部分/表单数据`。 (3认同)

GP *_*ngh 33

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


Pre*_*raj 11

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

  • 我相信 **enctype** 并不代表加密类型。此级别不涉及加密。我的猜测是编码类型或封闭类型。但肯定不是加密类型。 (10认同)

san*_*ndy 8

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

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