我知道这是一篇旧文章,但它仍然非常相关。我发现现代浏览器支持rfc5987,它允许utf-8编码,百分号编码(url编码)。那么朴素的file.txt将变成:
Content-Disposition: attachment
Safari (5) 不支持此功能。相反,您应该使用 Safari 标准,在 utf-8 编码的标头中直接编写文件名:
Content-Disposition: attachment
IE8及更早版本也不支持此功能,您需要使用IE标准的utf-8编码,百分比编码:
Content-Disposition: attachment
在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,所以我不能去掉第一部分。事实证明,安卓浏览器使用内置的安卓下载管理器,在标准方式下无法可靠地解析文件名。
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"))
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、Opera 12、FF25和Safari 6中进行了测试,使用以下文件名进行下载:你好abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§!#¤%&()=`@£$€{[]}+´¨^~'-_,;.txt。
在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上讨论的那样,它似乎不能很好地工作。
Content-Disposition: attachment
。 - Antti Haapala -- Слава Україні