http - 如何区分空文件和丢失文件的多部分表单数据?
问题描述
我尝试在服务器端区分上传空文件和未上传文件
空文件的 POST 正文内容为:
------WebKitFormBoundaryAYxCGhPMYcmdkdlv
Content-Disposition: form-data; name="_1"
dd
------WebKitFormBoundaryAYxCGhPMYcmdkdlv
Content-Disposition: form-data; name="_2"; filename="foo"
Content-Type: application/octet-stream
------WebKitFormBoundaryAYxCGhPMYcmdkdlv
Content-Disposition: form-data; name="_3"
Upload
------WebKitFormBoundaryAYxCGhPMYcmdkdlv--
虽然丢失的文件是
------WebKitFormBoundaryMldAHhbBqWpKPlRY
Content-Disposition: form-data; name="_1"
dd
------WebKitFormBoundaryMldAHhbBqWpKPlRY
Content-Disposition: form-data; name="_2"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryMldAHhbBqWpKPlRY
Content-Disposition: form-data; name="_3"
Upload
------WebKitFormBoundaryMldAHhbBqWpKPlRY--
唯一的区别是filename=
内容一个是空的,另一个包含文件名(Firefox 和 Chromium 的行为相同)
问题:
- 是否存在浏览器不提供
filename
(安全或类似的东西)的条件? - 区分空文件和非设置文件实际上是有效/标准的方法吗,请提供参考。
- 是
Content-Type: application/octet-stream
标准响应吗?在未上传文件的情况下会设置吗?
我希望看到一些对证实或反驳我的观察的标准的引用
解决方案
1. 文件名
“HTML 中基于表单的文件上传”的原始规范是RFC1867
根据该规范,filename
参数
“不是必需的,但在原始文件名已知的任何情况下都强烈建议使用”
该规范已被RFC2388 - “Returning Values from Forms: multipart/form-data”取代,其中指出
发送应用程序可以提供一个文件名……如RFC2184中指定的那样;
(RFC2184 继续强调它的重要性,但不需要它)
请注意,它指的是“发送应用程序”。该规范清楚地表明它与应用程序无关。然而,对于实际实现的跨浏览器视图,Mozilla 的 MDN 文档提供了FormData
一些启示。FormData.append()
在设置文件/blob但未明确设置文件名的上下文中:
Blob 对象的默认文件名是“blob”。File 对象的默认文件名是文件的文件名。
2.空文件和无文件的区别
要回答这个问题,请务必注意RFC2388的第 5.7 节- “将表单数据与原始表单相关联”
本规范没有提供特定机制,通过该机制 multipart/form-data 可以与导致其传输的表单相关联。这种分离是故意的...
然而,这在 HTML5 规范中得到了回答,该规范详细说明了表单数据的构造方式。
...如果字段元素是
<input>
类型属性处于文件上传状态的<input>
元素,则对于元素中选择的每个文件,在表单数据集中附加一个条目,名称为名称,文件(由名称、类型和正文)作为值,类型作为类型。如果没有选定的文件,则将一个条目附加到表单数据集,名称为名称,空字符串为值,application/octet-stream 为类型。
这符合您上面的观察。
看看现实世界的服务器实现如何处理这个问题,以 PHP 运行时为例。它的 API 没有区分“无文件”和“空文件”——UPLOAD_ERR_NO_FILE
在任何一种情况下都会引发一个错误。
由于 PHP 是开源的(用 C 编写),您可以在此处查看该实现
3. MIME 内容类型编码
这在上面的 #2 中得到了回答——正如 HTML5 规范中详述的那样,(来自兼容的浏览器)它总是application/octet-stream
在表单值为空的地方。
为了完整起见,如果提供了文件, RFC2388 指定:
如果通过填写表格返回文件的内容,则文件输入被标识为适当的媒体类型(如果已知)或“application/octet-stream”
推荐阅读
- excel - 使用 Excel / VBA 解析主机名的 IP 地址
- cmake - 如何在 Ubuntu 上为 Win32 交叉编译 Clang?
- xv6 - 这段代码在 xv6 entrypgdir 中是什么意思?
- python - Discord bot 在将命令移动到 cog 后不响应命令
- java - Twitter4J 转发一条消息
- java - 为什么 FileChanel.open() 而不是 RandomAccessFile.getChannel() 获得文件锁时可以移动文件
- node.js - Gridsome 开发请求失败,状态码为 404
- reactjs - 使用钩子 + 回调
- sage - Sage 不承认理想的单位
- php - 在 HTML/PHP 中创建电子邮件表单并在电子邮件中包含下拉选择、消息区域和附件