我知道这是一个老帖子,但它仍然非常相关。我发现现代浏览器支持rfc5987,它允许utf-8编码,百分比编码(url编码)。然后Naïve file.txt变成:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari(5)不支持这一点。相反,你应该使用Safari标准,直接在utf-8编码的头文件中写入文件名:
Content-Disposition: attachment; filename=Naïve file.txt
IE8及以上版本也不支持,你需要使用IE标准的utf-8编码,百分比编码:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
在ASP。Net我使用以下代码:
string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.Browser.Browser == "Safari")
contentDisposition = "attachment; filename=" + fileName;
else
contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);
我用IE7、IE8、IE9、Chrome 13、Opera 11、FF5、Safari 5测试了上述内容。
2013年11月更新:
这是我目前使用的代码。我仍然必须支持IE8,所以我不能摆脱第一部分。事实证明,Android上的浏览器使用内置的Android下载管理器,它不能可靠地以标准方式解析文件名。
string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\"";
else
contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);
上面现在测试在IE7-11, Chrome 32,歌剧12日FF25, Safari 6,使用该文件名下载:你好abcABCæø一ÆØAaouieeiaeiaouyn ½§!#¤%&()=`@£$ € {[]}+´¨^~'-_,;. 三种
在IE7上,它适用于某些字符,但不是所有字符。但是现在谁还关心IE7呢?
这是我用来为Android生成安全文件名的函数。注意,我不知道Android支持哪些字符,但我已经测试过了,这些字符肯定有效:
private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
char[] newFileName = fileName.ToCharArray();
for (int i = 0; i < newFileName.Length; i++)
{
if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
newFileName[i] = '_';
}
return new string(newFileName);
}
@TomZ:我在IE7和IE8中进行了测试,结果证明我不需要转义撇号(')。你能举个失败的例子吗?
@Dave Van den Eynde:根据RFC6266将两个文件名合并在一行中,除了Android和IE7+8,我已经更新了代码来反映这一点。谢谢你的建议。
@Thilo:不知道GoodReader或其他非浏览器。使用Android方法可能会有一些运气。
@Alex Zhukovskiy:我不知道为什么,但正如在Connect上讨论的那样,它似乎运行得不太好。