如何在 multipart/form-data HTTP POST 请求中指定字符编码?

How is character encoding specified in a multipart/form-data HTTP POST request?

HTML 5 规范描述了 algorithm 用于选择要在 multi-part 表单提交中使用的字符编码(例如 UTF-8)。但是,尚不清楚应如何将所选编码中继到服务器,以便在接收端正确解码内容。

通常,字符编码是通过将“字符集”参数附加到 Content-Type 请求 header 的值来表示的。但是,此参数似乎没有为 multipart/form-data MIME 类型定义:

https://www.rfc-editor.org/rfc/rfc7578#section-8

多部分表单提交中的每个部分都可以提供自己的 Content-Type header;然而,RFC 7578 指出“在实践中,许多广泛部署的实现并没有在每个部分中提供字符集参数,而是它们依赖于 'default charset' 用于 multipart/form-data 实例的概念”。 =17=]

RFC 7578 继续建议可以将隐藏的“_charset_”表单域用于此目的。但是,Safari (9.1) 和 Chrome (51) 似乎都没有填充此字段,它们也没有提供任何 per-part 编码信息。

我查看了两种浏览器产生的请求 headers,但没有看到任何明显的字符编码信息。有谁知道浏览器是如何将这些信息传送到服务器的?

HTML 5 使用 RFC 2388(被 RFC 7578 废弃),但是 HTML 5 明确地 删除了 Content-Type header 来自 non-file 个字段,而 RFC 没有:

The parts of the generated multipart/form-data resource that correspond to non-file fields must not have a Content-Type header specified. Their names and values must be encoded using the character encoding selected above (field names in particular do not get converted to a 7-bit safe encoding as suggested in RFC 2388).

RFC 旨在允许 multipart/form-data 除了 HTML 之外还可以在其他上下文中使用(尽管这是其最常见的用途)。在那些其他上下文中,Content-Type 是允许的。只是不在 HTML 5 中(但在 HTML 4 中是允许的)。

如果没有 Content-Type header,隐藏的 _charset_ 表单域(如果存在)是 HTML 5 <form> 提交者可以 明确地说明使用了哪个字符集。

根据您链接到的 HTML 5 算法规范,所选字符集必须从 <form> 元素的 accept-charset 属性中选择(如果存在),否则就是HTML本身如果是ASCII-compatible,否则就是UTF-8。这在算法规范以及 RFC 7578 第 5.1.2 节中提到 HTML 5.

时明确说明

因此,确实没有必要让网络浏览器 显式 声明字符集,因为表单提交的接收者应该知道期望的字符集凭借 <form> 的创建方式,因此可以在解析提交时检查那些字符集。如果接收者想知道使用的 specific 字符集,它需要在 <form>.

中包含一个隐藏的 _charset_ 字段