我正在使用在HttpHandler子项中实现的HttpContext对象来下载文件,当我在文件名中有非ascii字符时,它在IE中看起来很奇怪,而在Firefox中看起来很好。
下面是代码: -
context.Response.ContentType = ".cs";
context.Response.AppendHeader("Content-Length", data.Length.ToString());
context.Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}",filename));
context.Response.OutputStream.Write(data, 0, data.Length);
context.Response.Flush();
当我在文件名字段中提供''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''在文件名中它在firefox中看起来很好。添加EncodingType和charset是没有用的。
即是'ß''ä''ö''ü''ó³''ß' 'ä''ö''ü'_'ó³'并且在Firefox中它是'Ã''''''''''''''''''''''' ''Ã'''''''''。
任何想法如何解决这个问题?
答案 0 :(得分:16)
我有类似的问题。您必须使用HttpUtility.UrlEncode或Server.UrlEncode来编码文件名。另外我记得firefox不需要它。此外,当它是url编码时,它会破坏文件名。我的代码:
// IE needs url encoding, FF doesn't support it, Google Chrome doesn't care
if (Request.Browser.IsBrowser ("IE"))
{
fileName = Server.UrlEncode(fileName);
}
Response.Clear ();
Response.AddHeader ("content-disposition", String.Format ("attachment;filename=\"{0}\"", fileName));
Response.AddHeader ("Content-Length", data.Length.ToString (CultureInfo.InvariantCulture));
Response.ContentType = mimeType;
Response.BinaryWrite(data);
修改
我已经仔细阅读了规范。首先RFC2183表示:
当前[RFC 2045]语法将参数值(以及内容处理文件名)限制为US-ASCII。
但后来我发现[RFC 2045]已过时且必须引用RFC 2231的引用,其中指出:
星号(“*”)被重复使用 语言和语言的指标 字符集信息存在 正在使用编码。单身 quote(“'”)用于分隔 字符集和语言信息 在参数的开头 值。百分号(“%”)用作 编码标志,同意 RFC 2047。
这意味着您可以将UrlEncode用于非ascii符号,只要您包含rfc中所述的编码即可。这是一个例子:
string.Format("attachment; filename=\"{0}\"; filename*=UTF-8''{0}", Server.UrlEncode(fileName, Encoding.UTF8));
请注意,filename
除filename*
外还包含{{1}},以实现向后兼容性。您也可以选择其他编码并相应地修改参数,但UTF-8涵盖了所有内容。
答案 1 :(得分:7)
HttpUtility.UrlPathEncode可能是更好的选择。由于URLEncode将用'+'符号替换空格。
答案 2 :(得分:3)
对我来说,这个解决方案适用于所有主流浏览器:
Response.AppendHeader("Content-Disposition", string.Format("attachment; filename*=UTF-8''{0}", HttpUtility.UrlPathEncode(fileName).Replace(",", "%2C"));
var mime = MimeMapping.GetMimeMapping(fileName);
return File(fileName, mime);
使用ASP.NET MVC 3。
替换是必要的,因为Chrome在参数值中不喜欢逗号(,):http://www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/
答案 3 :(得分:2)
您可能需要阅读RFC 6266并查看http://greenbytes.de/tech/tc2231/处的测试。
答案 4 :(得分:1)
对我来说,这解决了这个问题:
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(data)
};
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = "foo-ä-€.html"
};
当我看到fiddler中的repsonse时,我可以看到文件名已经自动使用UTF-8进行编码:
Fiddler response example with encoded Content-Disposition filename using UTF-8
如果我们查看Content-Disposition标头的值,我们可以看到它与@Johannes Geyer的答案相同。唯一的区别是我们没有必要自己编码,ContentDispositionHeaderValue类负责处理。
我在Julian Reschke提到的http://greenbytes.de/tech/tc2231/上使用了Testcases for Content-Disposition标头。 有关ContentDispositionHeaderValue类的信息可以在MSDN上找到。
答案 5 :(得分:0)
对于Asp.Net Core(本文第2版)UrlPathEncode已弃用,以下是如何获得所需结果:
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = Uri.EscapeUriString(fileName),
Inline = true // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add("Content-Disposition", cd.ToString());
答案 6 :(得分:0)
我使用Uri.EscapeUriString
将所有字符转换为它们的十六进制表示,并将string.Normalize
用于Unicode规范化形式C。
(在ASP.NET MVC5框架4.5中测试)
var contentDispositionHeader = new System.Net.Mime.ContentDisposition
{
Inline = false,
FileName = Uri.EscapeUriString(Path.GetFileName(pathFile)).Normalize()
};
Response.Headers.Add("Content-Disposition", contentDispositionHeader.ToString());
string mimeType = MimeMapping.GetMimeMapping(Server.MapPath(pathFile));
return File(file, mimeType);