【问题标题】:Special Characters in Content-Disposition filenameContent-Disposition 文件名中的特殊字符
【发布时间】:2011-12-19 12:08:31
【问题描述】:

我的问题与How to encode the filename parameter of Content-Disposition header in HTTP? 重复 但是由于这个问题是很久以前提出的并且仍然没有令人满意的答案(在我看来),我想再问一次。

我开发了一个 C++ CGI 应用程序,它提供的文件名称中可能包含特殊字符,例如
"weird # € = { } ; filename.txt"

似乎不可能以适用于每个浏览器的方式设置 HTTP Content-Dispostion,例如

  • Internet Explorer
  • 火狐
  • 歌剧
  • 野生动物园

我很乐意为每个浏览器提供不同的解决方案。
现在这就是我走了多远:

Internet Explorer(添加双引号并替换 # 和 ; )

Content-Disposition: attachment; filename="weird %23 € = { } %3B filename.txt"

Firefox(双引号似乎可以工作。没什么可做的):

Content-Disposition: attachment; filename="weird # € = { } ; filename.txt"

另一种可行的选择:

Content-Disposition: attachment; filename*=UTF-8''weird%20%23%20%e2%82%ac%20%3D%20%7B%20%7D%20%3B%20filename.txt

当只使用双引号时会出现这些问题:

  • = 在文件名中消失
  • € 将被替换为 -

但这有效:

Content-Disposition: attachment; filename*=UTF-8''weird%20%23%20%e2%82%ac%20%3D%20%7B%20%7D%20%3B%20filename.txt

歌剧

使用双引号或使用语法:filename*=UTF-8''... 会产生以下问题:

  • 文件名中多个粘贴在一起的空格减少为一个
  • { 和 } 消失:“ab{}cd.txt” -> “abcd.txt
  • 文件名在 ; 之后被截断其中:“abc ; def.txt”->“abc

编辑 2: 这是因为文件名长度限制。此语法适用于 Opera:

Content-Disposition: attachment; filename*=UTF-8''weird%20%23%20%e2%82%ac%20%3D%20%7B%20%7D%20%3B%20filename.txt

Safari

  • € 将替换为不可见字符(使用双引号)

    no solution that prevents that little problem
    

其他线程(上面提到的)的建议使用

Content-Disposition: attachment; filename*=UTF-8''weird%20%23%20%80%20%3D%20%7B%20%7D%20%3B%20filename.txt

对我不起作用。转义字符不会被翻译回来,或者浏览器想要以我的 cgi 应用程序的名称保存到文件中。那是因为我的编码错误。我没有根据 RFC 5987 进行编码。但是 Safari 无论如何都没有使用这种编码。所以到目前为止还没有解决 € 字符的方法。

顺便说一句:UTF-8 转换器http://www.rishida.net/tools/conversion/

我在这些测试中使用了每个浏览器的最新版本:

  • 火狐7
  • Internet Explorer 9
  • 铬 15
  • Opera 11.5
  • Safari 5.1

PS:我尝试了键盘上的所有特殊字符。我在这个线程中只使用了那些制造麻烦的。

编辑:

我还在我的键盘上尝试了一个包含所有特殊字符的文件名(可能在文件名中),但它不像上面的测试字符串那样工作:

完整的测试字符串:

0 ! § $ % & ( ) = ` ´ { }    [ ] ² ³ @ € µ ^ ° ~ + ' # - _ . , ; ü ä ö ß 9.jpg

编码测试字符串:

0%20%21%20%C2%A7%20%24%20%25%20%26%20%28%20%29%20%3D%20%60%20%C2%B4%20%7B%20%7D%20%20%20%20%5B%20%5D%20%C2%B2%20%C2%B3%20%40%20%E2%82%AC%20%C2%B5%20%5E%20%C2%B0%20~%20%2B%20%27%20%23%20-%20_%20.%20%2C%20%3B%20%C3%BC%20%C3%A4%20%C3%B6%20%C3%9F%209.jpg

使用这种方法:

Content-Disposition: attachment; filename*=UTF-8''0%20%21%20%C2%A7%20%24%20%25%20%26%20%28%20%29%20%3D%20%60%20%C2%B4%20%7B%20%7D%20%20%20%20%5B%20%5D%20%C2%B2%20%C2%B3%20%40%20%E2%82%AC%20%C2%B5%20%5E%20%C2%B0%20~%20%2B%20%27%20%23%20-%20_%20.%20%2C%20%3B%20%C3%BC%20%C3%A4%20%C3%B6%20%C3%9F%209.jpg

我得到了以下结果:

  • Firefox 有效
  • Chrome 可以工作
  • IE: $ % & ( ) = ` ´ { } [ ] ² ³ @ € µ ^ ° ~ + ' # - _ 。 , ; ü ä ö ß 9.jpg(删除前 6 个字符)。 编辑 2: 这是因为浏览器的文件名长度限制。它开始从字符串的开头切断文件名。我没有深入研究,但看起来普通文件名可能有大约 200 个字符长,而具有许多转义序列的文件名甚至更多但少于 250 个。但没关系。
  • 歌剧:0! § $ % & ( ) = ` ´ [ ] ² ³ @ € µ ^ ° ~ + ' # - _ 。 , ; ü ä ö ß 9.jpg(像以前一样缺少一些字符)。 编辑 2: 我缩短了我的测试字符串,因为我怀疑 Opera 的文件名长度“问题”与 IE 一样,它也在那里工作。
  • Safari 不适用于该语法。那是例外。

编辑 2:

目前的状态是,语法 filename*=UTF-8''filname escape sequence" 适用于除 Safari 之外的所有浏览器。唯一被 Safari 替换的字符是 € . 我想我可以忍受。谢谢!

编辑 3:文件名长度

我注意到一些文件名长度问题。

  • Internet Explorer:文件名长度可以为 147 个字符。如果字符串不包含转义序列,那么这就是文件名的长度。如果是这样,文件名可能会有所不同。生成的文件名少于 147 个字符。但它不同。我使用了 2 个转义序列,文件名缩短了 5 个字符,我使用了许多转义序列,文件名缩短了 2 个字符。我在这里找不到规则。
  • 其他浏览器似乎没有这个问题。如果文件系统可以处理文件,他们会保存文件。例如,我尝试了 250 个字符,浏览器说我必须减少文件名 (Chrome),或者他们自己将其缩短为 220 (Opera) 或 210 (Firefox) 字符。 Opera 切断了文件的结尾。 Safari 尝试保存那个长文件名,但最终没有保存它,而是在下载列表中写入“-1”作为文件名。

【问题讨论】:

  • 如果你想引起人们对一个老问题的关注,你应该在上面发布一个赏金。转发是垃圾邮件。
  • 如果您想修复浏览器,请与供应商联系。这可能更有成效。在那之前,提供每个浏览器都能理解的文件名,为什么让它变得更复杂呢?
  • @hakre:用户可以选择任何他想要的文件名。我也不喜欢它,但我必须忍受它,并希望它适用于所有浏览器。
  • @juergend:从技术上讲,用户不能选择任何她想要的文件名。你不能在没有规范的情况下编码,否则你会遇到这样的问题。我可以尊重您愿意为用户提供广泛选择的意愿,但请记住,您无法满足所有人的愿望。例如文件名中的控制字符。保重。

标签: c++ browser http-headers cgi content-disposition


【解决方案1】:

Firefox、MSIE(从版本 9 开始)、Opera、Konq 和 Chrome 支持; MSIE8 和 Safari 不支持;其他支持未知 - RFC 5987 中定义的编码。

注意在

  Content-Disposition: attachment; filename*=UTF-8''weird%20%23%20%80%20%3D%20%7B%20%7D%20%3B%20filename.txt

你把欧元字符的编码弄错了;它的 unicode 代码点不是 %80,修复这个问题应该可以使它在除 Safari 之外的任何地方都能工作(正确的编码是 %e2%82%ac)。

测试用例在:

http://greenbytes.de/tech/tc2231/#attwithfn2231utf8

【讨论】:

  • 你是对的!看起来我在这里使用了错误的编码。我将对此进行调查并报告
  • 如何为不支持的用户代理提供后备方案?如何处理屏蔽或不提供用户代理字符串的用户代理?
  • hakre:我建议始终使用新的 RFC 5987 变体,并为旧版浏览器(如 Safari 和 IE 预版本 9)添加纯 ASCII 变体。另请参阅:greenbytes.de/tech/webdav /rfc6266.html#examples
  • juergen - 你能做最少的测试用例来演示 IE 和 Opera 问题吗?然后我可以将它们添加到我的测试套件中。谢谢。顺便说一句:请注意,UA 完全可以过滤掉某些字符,例如控件或路径分隔符;但看看他们以何种不同的方式做事会很有趣。
  • hakre - 后备取决于排序; IE8 需要首先查看全 ASCII 变体。见greenbytes.de/tech/tc2231/#attfnbothgreenbytes.de/tech/tc2231/#attfnboth2
猜你喜欢
  • 2016-11-06
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 2015-07-17
相关资源
最近更新 更多