ChatGPT解决这个技术问题 Extra ChatGPT

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

enctype='multipart/form-data' 在 HTML 表单中是什么意思,我们应该在什么时候使用它?

它用于将整个文件作为表单提交的一部分发布。我认为这可能与文本表单输入的多个部分有关,但事实并非如此,它只是用于文件上传。
我更喜欢 HTML 中的双引号

c
cellepo

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

HTML 表单提供 three methods of encoding

application/x-www-form-urlencoded (默认)

多部分/表单数据

文本/纯文本

正在完成添加 application/json 的工作,但已放弃。

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

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

永远不要使用文本/纯文本。

当您编写客户端代码时:

当您的表单包含任何 元素时使用 multipart/form-data

否则您可以使用 multipart/form-data 或 application/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 specification 中找到结果示例。

text/plain 由 HTML 5 引入,仅对调试有用——来自 the spec它们不能被计算机可靠地解释——我认为其他工具与工具(如 {2 } 在大多数浏览器的开发者工具中)更好)。


@Quentin 请问,如果我们对所有表单都使用 multipart,可能会出现什么问题?有和没有文件。
它对 GET 表单没有意义,并且它使请求的文件大小更大。
《HTML 表单提供三种编码方式》
因为它有多个部分
@MasterJoe,因为它可以有多个由边界分隔的数据项,请参阅 RFC 2046 section 5.1.1
C
Ciro Santilli Путлер Капут 六四事

我们什么时候应该使用它?

Quentin's answer 正确:如果表单包含文件上传,则使用 multipart/form-data,否则使用 application/x-www-form-urlencoded,如果省略 enctype,则使用默认值。

我要去:

添加更多 HTML5 引用

用表单提交示例解释为什么他是对的

HTML5 参考资料

enctypethree possibilities

应用程序/x-www-form-urlencoded

多部分/表单数据(规范指向 RFC7578)

文本/纯文本。这是“计算机无法可靠解释的”,因此绝不应该在生产中使用它,我们也不会进一步研究它。

如何生成示例

一旦您看到每种方法的示例,它们的工作原理以及何时应该使用每种方法就会变得很明显。

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

nc -l 或 ECHO 服务器:接受 GET/POST 请求的 HTTP 测试服务器

像浏览器或 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

创建要上传的文件:

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 localhost 8000; done

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

nc 打印收到的请求。

测试于: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 进行验证,它表示字节:

61 CF 89 62

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

因此很明显:

内容类型:multipart/form-data; boundary=----------------------------735323031399963166993862150 将内容类型设置为 multipart/form-data 并表示字段由给定的分隔边界字符串。但请注意:boundary=----------------------------735323031399963166993862150 比实际障碍少两个破折号 ----- ------------------------735323031399963166993862150 这是因为标准要求边界以两个破折号开头--。其他破折号似乎正是 Firefox 选择实现任意边界的方式。 RFC 7578 明确提到这两个前导破折号 - 是必需的:4.1。 multipart/form-data 的“Boundary”参数 与其他 multipart 类型一样,各部分由边界分隔符分隔,使用 CRLF、“--”和“boundary”参数的值构造。

每个字段在其数据之前都有一些子标题: Content-Disposition: form-data;,字段名称,文件名,然后是数据。服务器读取数据直到下一个边界字符串。浏览器必须选择一个不会出现在任何字段中的边界,因此这就是为什么边界在请求之间可能会有所不同。因为我们有唯一的边界,所以不需要对数据进行编码:二进制数据按原样发送。 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,重新加载浏览器,然后重新提交。

火狐发送:

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 这样的普通可打印字符以一个字节发送,而像 0xCF0x89 这样的不可打印字符占用 3 个字节每个:%CF%89

比较

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

从例子中我们看到:

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

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

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

但是对于在文本字段中找到的可打印字符,它并不重要并且产生的开销更少,所以我们只是使用它。


@Khanna111%CF 有 3 个字节长:%CF :-) 使其易于阅读的故事。
在 OS X 上,nc 不会同时接受 -l-p 参数。但这对我有用:while true; do printf '' | nc -l 8000; done
据我所知,将 ANY DASHES ATALL 放在边界上的目的是使无法通过肉眼检查请求的语法。请不要在边界令牌中使用它们。
@DewiMorgan你是完全正确的。我编辑了帖子并从边界字符串中删除了破折号。
@CiroSantilli冠状病毒审查六四事件轮法功关键不是边界字符串中的破折号不起作用。他们确实工作得很好。但是,正如 Dewi Morgan 所说:它们是不必要且高度混乱的,因为多部分/表单数据编码需要在每个边界之前和最后一个边界之后设置“--”。
M
Mohammed H

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

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


所以..如果文件不是二进制文件,那么没有这个我们可以工作吗?
据我了解,您可以使用 multipart/form-data 发送非二进制文件,但效率低下。我相信使用 application/x-www-form-urlencoded 是发送非二进制数据的正确方法,但对非二进制文件有更多经验的人可能需要纠正我。
使用 multipart/form-data 发送文件的主要优点是它可以在前端和后端自动工作。您不必进行任何特殊处理。所有文件都是二进制文件,即使它们应该只包含文本。 application/x-www-form-urlencoded 是发布不带附件的表单的标准方式。 multipart/form-data 是发布带有附件的表单的标准方式。 (还有许多其他编码,例如 application/jsonapplication/json-patch+json,它们在服务器和客户端之间的通信中很常见。)
值得指出的是,您可以对图像进行 base64 编码并将其作为纯字符串数据发送。
除了上面@Prospero 的评论:您绝对可以通过 POST 发送文件,而无需使用 multipart/form-data。你不能做的是使用普通的 HTML 表单提交,而不使用 JavaScript。将表单设置为使用 multipart/form-dataHTML 提供的唯一机制,可让您在不使用 JavaScript 的情况下发布文件。我觉得这在答案中不够清楚,天真的读者可能会认为没有 multipart/form-data 无法发送文件是 HTTP 的限制;事实并非如此。
C
Community

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

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

POST 告诉您的浏览器构建一个 HTTP 消息并将所有内容放在消息的正文中(一种非常有用的做事方式,更安全,也更灵活)。

GET 将在查询字符串中提交表单数据。它对数据表示和长度有一些限制。

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

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

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

application/x-www-form-urlencoded:这是默认设置。发送表单时,将收集所有名称和值,并对最终字符串执行 URL 编码。

multipart/form-data:字符未编码。当表单具有文件上传控件时,这一点很重要。您要发送文件二进制文件,这样可以确保比特流不会被更改。

text/plain:空格被转换,但不再执行编码。

安全

提交表单时,可能会出现一些安全问题,如 RFC 7578 Section 7: Multipart form data - Security considerations 中所述:

所有表单处理软件都应该敏感地对待用户提供的表单数据,因为它通常包含机密或个人识别信息。 Web 浏览器中广泛使用表单“自动填充”功能;这些可能被用来欺骗用户在完成其他无害的任务时在不知不觉中发送机密信息。 multipart/form-data 不提供任何用于检查完整性、确保机密性、避免用户混淆或其他安全功能的功能;这些问题必须通过表格填写和表格数据解释应用程序来解决。接收表单并处理它们的应用程序必须小心不要将不打算发送的数据提供回请求表单处理站点。在解释 Content-Disposition 标头字段的文件名时,重要的是不要无意中覆盖收件人文件空间中的文件。

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


最近一次编辑后的安全问题与enctype的作用无关。我知道它确实来自 multipart/form-data RFC,但它是关于提交表单的安全考虑的任意转储,这些表单与数据是以 application/x-www-form-urlencoded 还是 multipart/form-data 形式发送完全正交。
V
Volker E.

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


s
sandy

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

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


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

enctype(ENCode TYPE) 属性指定表单数据在提交到服务器时应如何编码。

multipart/form-data 是 enctype 属性的值之一,用于有文件上传的表单元素。多部分是指表单数据分成多个部分并发送到服务器。


我相信 enctype 不代表加密类型。此级别不涉及加密。我的猜测是编码类型或封闭类型。但肯定不是加密类型。
您在此处关于 <head><body> 的最后一个要点是无关紧要且令人困惑的。
E
Eric

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


f
fatima hassan

如果用户将通过表单上传文件,则此值是必需的

请阅读本文

https://www.w3schools.com/tags/att_form_enctype.asp


P
Pang

enctype 属性指定表单数据在提交到服务器时应如何编码。仅当 method="post" 时才能使用 enctype 属性。没有字符被编码。当您使用具有文件上传控件的表单时,此值是必需的

来自W3Schools


这句话甚至没有提到multipart/form-data。这也很不清楚。 “没有字符被编码”这句话是什么意思? -1。