What does enctype='multipart/form-data' mean?
What does enctype=’multipart/form-data’ mean?
技术背景
在进行 POST 请求时,需要对请求体中的数据进行编码。HTML 表单提供了三种编码方法:application/x-www-form-urlencoded
(默认值)、multipart/form-data
和 text/plain
。此外,曾有计划添加 application/json
编码方式,但该计划已被放弃。
实现步骤
选择合适的编码类型
- 客户端代码编写:
- 当表单包含
<input type="file">
元素时,使用multipart/form-data
。 - 若表单不包含文件上传元素,可使用
multipart/form-data
或application/x-www-form-urlencoded
,但application/x-www-form-urlencoded
效率更高。
- 当表单包含
- 服务器端代码编写:使用预写的表单处理库,如 Perl 的
CGI->param
或 PHP 的$_POST
超全局变量,这些库会处理不同编码格式的差异,无需手动解析服务器接收到的原始输入。
生成示例
可以使用 nc -l
或 ECHO 服务器,以及浏览器或 cURL 等用户代理来生成示例。以下是具体步骤:
- 将表单保存到一个最小的
.html
文件中:
1 |
|
- 创建要上传的文件:
1 |
|
- 运行 ECHO 服务器:
1 |
|
- 在浏览器中打开 HTML 文件,选择文件并点击提交,然后检查终端输出。
核心代码
multipart/form-data 示例
Firefox 发送的请求示例:
1 |
|
application/x-www-form-urlencoded 示例
将 enctype
改为 application/x-www-form-urlencoded
后,Firefox 发送的请求示例:
1 |
|
最佳实践
- 避免使用
text/plain
编码,因为它不易被计算机可靠解析,仅适用于调试。 - 当表单包含文件上传时,使用
multipart/form-data
编码。 - 对于不包含文件上传的表单,优先使用
application/x-www-form-urlencoded
编码,因为它效率更高。 - 在服务器端,使用预写的表单处理库来处理表单数据,避免手动解析原始输入。
常见问题
为什么 multipart/form-data
中的边界字符串比 Content-Type
中指定的边界多两个连字符?
这是因为标准要求边界字符串以两个连字符 --
开头。其他连字符是浏览器实现任意边界的方式。
application/x-www-form-urlencoded
为什么不适合用于文件上传?
application/x-www-form-urlencoded
会对非打印字符进行编码,每个非打印字符会增加 3 倍的开销。文件上传通常包含大量非打印字符,使用该编码方式会导致效率低下。此外,application/x-www-form-urlencoded
只会发送文件名,而不会发送文件内容。
如何确定上传文件的 Content-Type
?
浏览器会自动确定上传文件的 Content-Type
,具体确定方式可参考:https://stackoverflow.com/questions/1201945/how-is-mime-type-of-an-uploaded-file-determined-by-browser。
表单提交时的安全问题有哪些?
根据 RFC 7578 Section 7,表单处理软件应谨慎处理用户提供的表单数据,因为其中可能包含机密或个人识别信息。multipart/form-data
本身不提供完整性检查、保密性保证、避免用户混淆等安全功能,这些问题需要由表单填充和表单数据解释应用程序来解决。接收和处理表单的应用程序必须小心,不要将未打算发送的数据返回给请求的表单处理站点。在解释 Content-Disposition
头字段中的文件名时,要注意不要意外覆盖接收方文件空间中的文件。