Appendix A. 相对于 RFC 2616 定义的变更
相对于 [RFC2616] 第 19.5.1 节, 本规范做出了以下反映实际实现情况的规范性变更:
-
根据 RFC 2616, disposition type "attachment" 仅适用于类型为 "application/octet-stream" 的内容. 本规范删除了这一限制, 因为 recipient 在实践中并不检查内容类型, 而且该限制也会阻碍对媒体类型进行正确声明.
-
RFC 2616 仅允许 filename 参数使用 "quoted-string". 这会形成一种例外的参数语法, 也不符合实际使用情况.
-
本规范重新加入了 disposition type "inline" 的定义 ([RFC2183] 第 2.1 节), 并给出了处理建议.
-
本规范要求支持 [RFC5987] 中定义的扩展参数编码.
Appendix B. 与 RFC 2183 相比的差异
[RFC2183] 第 2 节定义了若干额外的 disposition 参数: "creation-date", "modification-date", "quoted-date-time" 和 "size". 大多数 user agent 并未实现这些参数, 因此本规范将它们省略.
Appendix C. 国际化的替代方法
默认情况下, HTTP 头字段参数不能承载 ISO-8859-1 ([ISO-8859-1]) 字符编码之外的字符 (见 [RFC2616] 第 2.2 节). 对于 "filename" 参数来说, 这显然是不可接受的限制.
遗憾的是, user agent 实现者尚未形成一种可互操作的方法, 尽管 IETF Standards Track 已经明确规定了唯一的解决方案 ([RFC2231], 并在 [RFC5987] 中针对 HTTP 加以澄清和 profile 化).
为完整起见, 以下各节描述已经尝试过的各种方法, 并解释它们为何不如本规范所使用的 RFC 5987 编码.
C.1. RFC 2047 编码
RFC 2047 为头字段定义了一种编码机制, 但该编码不应被用于头字段参数 -- 见 [RFC2047] 第 5 节:
'encoded-word' MUST NOT 出现在 'quoted-string' 内.
...
'encoded-word' MUST NOT 用于 MIME Content-Type 或 Content-Disposition 字段的参数中, 也不得用于任何结构化字段体中, 除非它位于 'comment' 或 'phrase' 内.
在实践中, 有些 user agent 实现了这种编码, 有些没有实现 (从而将编码后的字符串暴露给用户), 还有一些会因此产生混淆.
C.2. 百分号编码
有些 user agent 接受 percent-encoded ([RFC3986] 第 2.1 节) 字符序列. 用于解码的字符编码取决于多种因素, 包括引用页面的编码, user agent 的 locale, 其配置, 以及参数的实际值.
在实践中, 这种方法很难使用, 因为不支持它的 user agent 会向用户显示转义后的字符序列. 对于确实实现了这种方法的 user agent, 也很难预测它们实际期望哪一种字符编码.
C.3. 编码嗅探
有些 user agent 会检查该值 (对于 quoted-string 形式, 默认解释为 ISO-8859-1), 并在 UTF-8 看起来更可能是正确解释时切换到 UTF-8.
与上述方法一样, 这并不具备互操作性, 而且还存在误解实际值的风险.
Appendix D. 生成 Content-Disposition 头字段的建议
为了与现有和未来的 user agent 成功互操作, 建议 Content-Disposition 头字段的 sender:
-
当 US-ASCII ([US-ASCII]) 足以表达时, 包含 "filename" 参数.
-
仅在 filename 参数不包含禁止字符 (例如空格) 时使用其 'token' 形式; 在这类情况下, 应使用 quoted-string 形式.
-
避免在 filename 参数中包含百分号后跟两个十六进制字符 (例如 %A9), 因为一些现有实现会将其视为转义字符, 而另一些实现则会原样传递.
-
避免在 filename 参数的 quoted-string 形式中包含 "\" 字符, 因为一些 user agent 并未实现转义, 且 "\" 可能被视为非法路径字符.
-
避免在 filename 参数中使用非 ASCII 字符. 虽然大多数现有实现会将它们按 ISO-8859-1 解码, 但有些实现会应用启发式方法检测 UTF-8, 因而可能在某些名称上失败.
-
当期望的文件名无法使用 "filename" 形式忠实表达时, 包含 "filename*" 参数. 注意, 旧版 user agent 不会处理该参数, 而是会回退使用 "filename" 参数的内容.
-
发送 "filename*" 参数时, 如果可能, 同时生成 "filename" 参数, 作为不支持 "filename*" 形式的 user agent 的回退. 这可以通过将字符替换为 US-ASCII 序列来完成 (例如, 将 Unicode 字符点 U+00E4 (LATIN SMALL LETTER A WITH DIARESIS) 替换为 "ae"). 注意, 在某些 locale 中这可能无法做到.
-
当按上述方式包含 "filename" 参数作为回退时, 由于一些现有实现存在解析问题, "filename" 应首先出现.
-
当存在 "filename*" 参数时, 使用 UTF-8 作为其编码, 因为至少有一个现有实现只实现了这种编码.
注: 这些建议基于撰写本文时的 UA 行为, 以后可能会被取代. 在本文档发布时, http://purl.org/NET/http/content-disposition-tests 提供了各种实现当前支持水平的概览.