【问题标题】:Downloading file with ";" or "#" in file name ruins filename用“;”下载文件或文件名中的“#”会破坏文件名
【发布时间】:2009-03-29 20:52:07
【问题描述】:

我有一个名为 AttachmentDownload.aspx 的文件,并且在 Page_Load 方法中有这样的代码,可以下载文件。除包含“;”的名称外,所有名称在 IE 中都能正常工作或者 ”#”。他们提供用户以“AttachmentDownload.aspx”名称保存文件。有解决办法吗?

这是一个例子:

var fileName = Server.UrlPathEncode (";%.txt");
Response.AddHeader("content-disposition", String.Format("attachment;filename=\"{0}\"", fileName));
Response.WriteFile(path);
Response.End();

【问题讨论】:

  • 你试过编码吗?不知道它是否会有所帮助,但是; = %3B 和 # = %23
  • 嗯,我想过这个,但 Server.UrlPathEncod 不应该这样做吗?

标签: asp.net


【解决方案1】:

所有名称在 IE 中都能正常工作,但包含“;”的名称除外或“#”。

我无法用“#”重现问题,但“;”肯定会破坏它。 '"' 和 '\' 也是如此(在 Unix 上你可以在文件名中使用它们,这会破坏你的引用字符串)。

在 RFC822 系列参数化标头(例如 Content-Disposition)中包含带外字符的“正确”解决方案在 RFC1521 中定义:不能包含在“令牌”中的字符串应包装在带引号的字符串,RFC2822 定义为将 " 和 \ 字符反斜杠转义,然后用引号括起来。

RFC2231 然后用一种非常复杂的方式扩展它,在头参数中包含非 ASCII 字符,理论上你会希望用它来支持 Unicode 字符。

在实践中:HTTP 并不是真正的 RFC822 系列规范,这些东西在常规浏览器中都不起作用(Opera 中的反斜杠转义除外)。没有可靠的方法可以将 Unicode Content-Disposition 文件名发送给客户端,而您的 ';' 问题不是因为任何转义问题,而是因为 IE 无法解析太妃糖的参数化标头(它在字符串中的下一个分号,即使它被引号包围)。

对于可靠的跨浏览器文件名设置,您可以在现实世界中采用两种方法:

  1. 在将文件名放入 Content-Disposition 标头之前,从文件名中删除任何令人反感的内容。这包括前导/尾随空格/点、大多数其他标点符号和任何非 ASCII。

  2. 根本不要在 Content-Disposition 标头中指定文件名,让浏览器从 URL 的最后部分计算出要使用的文件名。要阻止它选择“AttachmentDownload.aspx”,您可以将任何您喜欢的作为尾随 URL 部分,例如:

    http://www.example.com/AttachmentDownload.aspx/Foo%23Bar

这要求您使用纯 URL 编码和使用 UTF-8 的 Unicode 字符对大多数标点符号进行编码,但至少您可以输入这些字符。上述结果会导致文件下载提示“Foo;Bar”。

请注意,即使您可以在这样的 URL 路径部分对 Windows 不友好的字符(例如 '"' )进行编码,对于下载的文件,最好不要这样做,因为 IE 会通过尝试保存来响应在文件名中使用 '"' 的文件,并且会默默地神秘地响应失败。

【讨论】:

    【解决方案2】:

    我开始清理所有特殊字符的文件名。我想出了一个映射表,应该映射大多数常用字符。

    //http://www.pjb.com.au/comp/diacritics.html
    private static string[,] CharacterReplacements = { 
        { " ", "-"},
        { "&", "-"},
        { "?", "-"},
        { "!", "-"},
        { "%", "-"},
        { "+", "-"},
        { "#", "-"},
        { ":", "-"},
        { ";", "-"},
        { ".", "-"},
    
        { "¢", "c" },   //cent
        { "£", "P" },   //Pound
        { "€", "E" },   //Euro
        { "¥", "Y" },   //Yen
        { "°", "d" },   //degree
        { "¼", "1-4" }, //fraction one-quarter
        { "½", "1-2" }, //fraction half    
        { "¾", "1-3" }, //fraction three-quarters}
        { "@", "AT)"}, //at                                                  
        { "Œ", "OE" },  //OE ligature, French (in ISO-8859-15)        
        { "œ", "oe" },  //OE ligature, French (in ISO-8859-15)        
    
        {"Å","A" },  //ring
        {"Æ","AE"},  //diphthong
        {"Ç","C" },  //cedilla
        {"È","E" },  //grave accent
        {"É","E" },  //acute accent
        {"Ê","E" },  //circumflex accent
        {"Ë","E" },  //umlaut mark
        {"Ì","I" },  //grave accent
        {"Í","I" },  //acute accent
        {"Î","I" },  //circumflex accent
        {"Ï","I" },  //umlaut mark
        {"Ð","Eth"}, //Icelandic
        {"Ñ","N" },  //tilde
        {"Ò","O" },  //grave accent
        {"Ó","O" },  //acute accent
        {"Ô","O" },  //circumflex accent
        {"Õ","O" },  //tilde
        {"Ö","O" },  //umlaut mark
        {"Ø","O" },  //slash
        {"Ù","U" },  //grave accent
        {"Ú","U" },  //acute accent
        {"Û","U" },  //circumflex accent
        {"Ü","U" },  //umlaut mark
        {"Ý","Y" },  //acute accent
        {"Þ","eth"}, //Icelandic - http://en.wikipedia.org/wiki/Thorn_(letter)
        {"ß","ss"},  //German
    
        {"à","a" },  //grave accent
        {"á","a" },  //acute accent
        {"â","a" },  //circumflex accent
        {"ã","a" },  //tilde
        {"ä","ae"},  //umlaut mark
        {"å","a" },  //ring
        {"æ","ae"},  //diphthong
        {"ç","c" },  //cedilla
        {"è","e" },  //grave accent
        {"é","e" },  //acute accent
        {"ê","e" },  //circumflex accent
        {"ë","e" },  //umlaut mark
        {"ì","i" },  //grave accent
        {"í","i" },  //acute accent
        {"î","i" },  //circumflex accent
        {"ï","i" },  //umlaut mark
        {"ð","eth"}, //Icelandic
        {"ñ","n" },  //tilde
        {"ò","o" },  //grave accent
        {"ó","o" },  //acute accent
        {"ô","o" },  //circumflex accent
        {"õ","o" },  //tilde
        {"ö","oe"},  //umlaut mark
        {"ø","o" },  //slash
        {"ù","u" },  //grave accent
        {"ú","u" },  //acute accent
        {"û","u" },  //circumflex accent
        {"ü","ue"},  //umlaut mark
        {"ý","y" },  //acute accent
        {"þ","eth"}, //Icelandic - http://en.wikipedia.org/wiki/Thorn_(letter)
        {"ÿ","y" },  //umlaut mark
        };
    

    或者你可以在这里获取整个代码:

    http://remy.supertext.ch/2012/08/clean-filenames/

    如果您发现缺少的字符,请告诉我。

    【讨论】:

      【解决方案3】:

      带有特殊符号的文件名(例如:空格;# @ ! $ )或非 Unicode 字符要么不被某些浏览器支持,要么导致客户端机器中的文件名不正确。 这是一个叫chanext的中国人的文章,他给出了一个完美的方法来解决这个问题: 本文给出了一个示例代码(用 c# 编写)来展示如何在所有四种流行的浏览器(IE;Opera;Firefox 和 Chrome)中完美解决这个问题 文件名“Microsoft.Asp.Net.doc”和“File;;!@%#^&y.doc”都可以按照本文作者提供的方式正确输出。

      http://ciznx.com/post/aspnetstreamdownloaddisplaynonunicodespacechar.aspx

      【讨论】:

      • 对我来说实际上适用于不同浏览器的唯一解决方案,但我在文件名周围添加了双引号
      • 链接好像坏了
      【解决方案4】:

      UrlPathEncode 只对类似 URL 的字符串的“路径”部分进行编码,尝试使用 Server.UrlEncodeHttpUtility.UrlEncode

      【讨论】:

      • 这些编码都不适合像 Content-Disposition 这样的参数化标头。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      相关资源
      最近更新 更多