内容处理文件名中的特殊字符

Special Characters in Content-Disposition filename

本文关键字:特殊字符 文件名 处理      更新时间:2023-10-16

我的问题是如何在HTTP中编码内容处理头的文件名参数的副本?但是既然这个问题已经问了很久了,而且(在我看来)仍然没有令人满意的答案,我想再问一遍。

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

似乎不可能将HTTP内容处理设置为适用于每个浏览器的方式,如

  • Internet Explorer
  • Firefox
  • Chrome
  • 歌剧
  • Safari

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

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

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

Firefox(双引号似乎有效。Nothing more to do):

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
Chrome

当只使用双引号时,会出现以下问题:

  • =在文件名中消失
  • €将被-
  • 取代

但这是有效的:

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"

EDIT 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并没有使用这种编码。所以到目前为止还没有解决€字符的方法。

BTW:一个UTF-8转换器http://www.rishida.net/tools/conversion/

我使用了所有浏览器的最新版本来进行这些测试:

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

编辑2:

目前的情况是,语法filename*=UTF-8 "文件名转义序列"适用于除Safari以外的所有浏览器。唯一被Safari取代的字符是€。我想我可以接受。谢谢你!

EDIT 3:文件名长度

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

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