blog
blog copied to clipboard
RFC 1867 文件上传
HTML FORM 的调整
1867 首先对 HTML 的 form
元素进行了两处改变:
- 对
input
元素的type
属性增加一个file
属性 - 对
input
元素增加一个accept
属性,表示允许的文件类型
当使用 form
进行文件上传时,enctype
应设为 multipart/form-data
。此后当对 form 进行 submit 时,会使用 form-data 的格式发送 HTTP 请求。
要注意的是,当 form
元素中含有 input type=file
而没有设置 enctype
时,行为是未定义的。
If a form contains
<INPUT TYPE=file>
elements but does not contain an ENCTYPE in the enclosing<FORM>
, the behavior is not specified.
建议的实现
浏览器应该如何实现 type="file"
的 input
元素
RFC 中提到需要一个显示文件名的区域和一个用于选择文件的按钮。当 accept
属性存在时,文件选择器还需要约束可以选择文件类型。
使用效率更高的 multipart/form-data
而不是 application/x-www-form-urlencoded
The encoding type application/x-www-form-urlencoded is inefficient for sending large quantities of binary data or text containing non-ASCII characters.
额外的功能
加密与解密
multipart/form-data
不负责加解密。而有部分链路层协议会在链路层进行自动的加密与解密,有此需求的可以自行实现(或使用 HTTPS)。
延迟文件上传
有时候文件上传不一定需要,服务器可能需要先验证其余字段是否有效,然后才允许进行文件的上传。对此需求 RFC 的建议是拆分成多个 form
进行提交,将文件上传的协议保持简单。
使 input
元素过重?
对使用 input
元素实现文件上传,RFC 中认为不会使其职责过重,反而迁移和兼容更易实现。
上传外部文件
使用 message/external-body
并设置 access-type: uri:xxxx
可以上传第三方的文件。
但这个用得不多,而且没有实际操作过。(别人也不会轻轻松松让你拿到文件的 uri 地址啊。。)
multipart/form-data 定义
RFC 中的例子一:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
每个 form
表单元素由 boundary
进行分隔提交。每个属性都有 content-disposition
和 name
属性,对文件,还有表示原始文件名的 filename
属性。
默认表单元素的 Content-type
为 text/plain
;文件为 application/octet-stream
或可自动检测到的类型;多个文件时为 multipart/mixed
(见下面例子)。
当上传多个文件时,RFC 给出的例子二:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"
Content-type: multipart/mixed, boundary=BbC04y
--BbC04y
Content-disposition: attachment; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-disposition: attachment; filename="file2.gif"
Content-type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--
文件的 Content-type
属性被设置为 multipart/mixed
,并启用了一个新的 boundary
(相当于是一个嵌套形式)。每个文件使用新的 boundary
分隔,content-disposition
被设为 attachment
.
content-transfer-encoding
被设置为 binary
,指明该文件以二进制编码。
Each part may be encoded and the "content-transfer-encoding" header supplied if the value of that part does not conform to the default encoding.