enctype='multipart/form-data'在HTML表单中意味着什么?我们应该何时使用它?
当前回答
我们应该什么时候使用它?
Quentin的答案是正确的:如果表单包含文件上载,则使用multipart/form数据,否则使用application/x-www-form-urlencoded,如果省略enctype,则默认使用。
我要:
添加更多HTML5引用用一个表单提交示例解释他为什么是正确的
HTML5引用
enctype有三种可能:
应用程序/x-wwww-form-urlencoded多部分/表单数据(规范指向RFC7578)text/plain。这是“计算机无法可靠解释的”,因此它不应用于生产,我们也不会进一步研究。
如何生成示例
一旦你看到了每种方法的一个例子,你就会明白它们是如何工作的,以及你应该何时使用每种方法。
可以使用以下方法生成示例:
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ω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>
我们将默认文本值设置为ω;b、 这意味着ω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
运行我们的小型echo服务器:
while true; do printf '' | nc -l localhost 8000; done
在浏览器上打开HTML,选择文件,然后单击提交并检查终端。
nc打印收到的请求。
测试版本:Ubuntu 14.04.3,nc BSD 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(UTF-8中的aωb)按字面形式发送。您可以使用nc-l localhost 8000|hd进行验证,其中表示字节:
61 CF 89 62
已发送(61==“a”和62==“b”)。
因此,很明显:
内容类型:多部分/表单数据;boundary=-------------------------7353230313999963166993862150将内容类型设置为多部分/表单数据,并表示字段由给定的边界字符串分隔。但请注意:边界=-------------------------7353230313999963166993862150比实际屏障少两个破折号-----------------------------735323031399963166993862150这是因为标准要求边界以两个破折号--开头。其他破折号似乎正是Firefox选择实现任意边界的方式。RFC 7578明确提到,这两个前导破折号是必需的:4.1.多部分/表单数据的“边界”参数与其他多部分类型一样,这些部分用边界分隔符,使用CRLF、“--”和“边界”参数。每个字段在其数据之前都会得到一些子标题: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内容类型由浏览器自动确定。它是如何被精确地确定的问题是:上传文件的mime类型是如何被浏览器确定的?
应用程序/x-wwww-form-urlencoded
现在将enctype更改为application/x-wwww-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数据:为消息添加几个字节的边界开销,并且必须花费一些时间来计算,但每个字节都是一个字节。application/x-wwww-form-urlencoded:每个字段有一个单字节边界(&),但为每个不可打印字符添加3x的线性开销因子。
因此,即使我们可以发送带有application/x-www-form-urlencoded的文件,我们也不想这样做,因为这样效率太低了。
但对于文本字段中的可打印字符,这无关紧要,并且产生的开销也较少,所以我们只使用它。
其他回答
当您发出POST请求时,必须以某种方式对构成请求主体的数据进行编码。
HTML表单提供了三种编码方法。
application/x-wwww-form-urlencoded(默认值)多部分/表单数据文本/普通
添加application/json的工作已经完成,但已经放弃。
(使用HTML表单提交以外的其他方式生成的HTTP请求也可以进行其他编码。JSON是web服务的常用格式,有些仍然使用SOAP。)
格式的细节对大多数开发人员来说并不重要。要点如下:
切勿使用文本/纯文本。
编写客户端代码时:
当表单包含任何<input-type=“file”>元素时,请使用multipart/form数据否则,您可以使用multipart/form数据或application/x-www-form-urlencoded,但application/x-ww-form-urlencode将更有效
编写服务器端代码时:
使用预先编写的表单处理库
大多数(如Perl的CGI->param或PHP的$_POST超级全局公开的参数)都会为您处理这些差异。不要费心分析服务器接收的原始输入。
有时您会发现一个库不能同时处理这两种格式。Node.js最流行的处理表单数据的库是主体解析器,它不能处理多部分请求(但有文档推荐了一些可以处理的替代方案)。
如果您正在编写(或调试)用于解析或生成原始数据的库,那么您需要开始担心格式。出于兴趣,你可能也想了解一下。
application/x-www-form-urlencoded与URL末尾的查询字符串大致相同。
multipart/form数据要复杂得多,但它允许将整个文件包含在数据中。结果的一个例子可以在HTML4规范中找到。
text/plain是HTML5引入的,仅用于调试-从规范来看:它们不能被计算机可靠地解释-我认为其他与工具(如大多数浏览器的开发工具中的网络面板)相结合的工具更好)。
通常这是当您有一个POST表单,需要将文件上载作为数据。。。这将告诉服务器它将如何对传输的数据进行编码,在这种情况下,它不会被编码,因为它只会将文件传输并上传到服务器,例如,当上传图像或pdf时
将方法属性设置为POST,因为不能使用表单将文件内容放入URL参数中。
将enctype的值设置为multipart/form数据,因为数据将被拆分为多个部分,每个文件一个,以及可能随它们一起发送的表单正文文本一个。
我们应该什么时候使用它?
Quentin的答案是正确的:如果表单包含文件上载,则使用multipart/form数据,否则使用application/x-www-form-urlencoded,如果省略enctype,则默认使用。
我要:
添加更多HTML5引用用一个表单提交示例解释他为什么是正确的
HTML5引用
enctype有三种可能:
应用程序/x-wwww-form-urlencoded多部分/表单数据(规范指向RFC7578)text/plain。这是“计算机无法可靠解释的”,因此它不应用于生产,我们也不会进一步研究。
如何生成示例
一旦你看到了每种方法的一个例子,你就会明白它们是如何工作的,以及你应该何时使用每种方法。
可以使用以下方法生成示例:
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ω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>
我们将默认文本值设置为ω;b、 这意味着ω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
运行我们的小型echo服务器:
while true; do printf '' | nc -l localhost 8000; done
在浏览器上打开HTML,选择文件,然后单击提交并检查终端。
nc打印收到的请求。
测试版本:Ubuntu 14.04.3,nc BSD 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(UTF-8中的aωb)按字面形式发送。您可以使用nc-l localhost 8000|hd进行验证,其中表示字节:
61 CF 89 62
已发送(61==“a”和62==“b”)。
因此,很明显:
内容类型:多部分/表单数据;boundary=-------------------------7353230313999963166993862150将内容类型设置为多部分/表单数据,并表示字段由给定的边界字符串分隔。但请注意:边界=-------------------------7353230313999963166993862150比实际屏障少两个破折号-----------------------------735323031399963166993862150这是因为标准要求边界以两个破折号--开头。其他破折号似乎正是Firefox选择实现任意边界的方式。RFC 7578明确提到,这两个前导破折号是必需的:4.1.多部分/表单数据的“边界”参数与其他多部分类型一样,这些部分用边界分隔符,使用CRLF、“--”和“边界”参数。每个字段在其数据之前都会得到一些子标题: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内容类型由浏览器自动确定。它是如何被精确地确定的问题是:上传文件的mime类型是如何被浏览器确定的?
应用程序/x-wwww-form-urlencoded
现在将enctype更改为application/x-wwww-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数据:为消息添加几个字节的边界开销,并且必须花费一些时间来计算,但每个字节都是一个字节。application/x-wwww-form-urlencoded:每个字段有一个单字节边界(&),但为每个不可打印字符添加3x的线性开销因子。
因此,即使我们可以发送带有application/x-www-form-urlencoded的文件,我们也不想这样做,因为这样效率太低了。
但对于文本字段中的可打印字符,这无关紧要,并且产生的开销也较少,所以我们只使用它。
enctype='multipart/form-data'表示不会编码任何字符。这就是为什么在将文件上载到服务器时使用这种类型。因此,当表单需要上传二进制数据(如文件内容)时,使用multipart/form数据
推荐文章
- 为什么我的CSS3媒体查询不能在移动设备上工作?
- 下一个元素的CSS选择器语法是什么?
- 我如何用CSS跨浏览器绘制垂直文本?
- 如何获得box-shadow在左侧和右侧
- 相对定位一个元素,而不占用文档流中的空间
- 如何在jQuery检索复选框值
- 禁用身体滚动
- 如何在删除前显示确认消息?
- 在一个CSS宽度的小数点后的位置是尊重?
- 我怎么能选择一个特定的类的最后一个元素,而不是父里面的最后一个孩子?
- 反应:为什么当道具改变时子组件不更新
- 我怎么能检查html元素,从DOM消失失去焦点?
- 在Atom编辑器中是否有格式化HTML的命令?
- 把<script>标签放在</body>标签之后是错误的吗?
- 谷歌Chrome表单自动填充和它的黄色背景