Content-Disposition 标头中的 Unicode
-
23-09-2019 - |
题
我正在使用 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();
当我在文件名字段中提供 'Ù' '¤' '¶' 'Õ' 'Ú' 'Ù' '¤' '¶' 'Ñ' 'Ú' 时,它看起来与我在文件中的不同名字它在火狐浏览器中看起来不错。添加 EncodingType 和 charset 没有用。
在 ie 中是 'å¸''ä''ö''ü''ó''ß''ä''ö''�'_'��,在 Firefox 中是 '�' '�' '�¶' '���' '�' '�' '��' '�¶' '���' ��。
知道如何解决这个问题吗?
解决方案
我有类似的问题。你必须使用 HttpUtility.UrlEncode 或者 服务器.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, ,其中指出:
重复使用星号(“*”)以提供以下指标:语言和字符集存在并使用编码。单个报价(“'”)用于在参数值开始时界定字符集和语言信息。百分比(“%”)用作编码标志,与RFC 2047一致。
这意味着您可以对非 ascii 符号使用 UrlEncode,只要您包含中所述的编码即可 射频卡. 。这是一个例子:
string.Format("attachment; filename=\"{0}\"; filename*=UTF-8''{0}", Server.UrlEncode(fileName, Encoding.UTF8));
注意 filename
还包括 filename*
为了向后兼容。您还可以选择其他编码并相应地修改参数,但 UTF-8 涵盖了所有内容。
其他提示
HttpUtility.UrlPathEncode可能是一个更好的选择。正如将URLEncode的替换 '+' 标志位。
对我来说,这个解决方案适用于所有主要浏览器:
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。
Replace 是必要的,因为 Chrome 不喜欢在参数值中使用逗号 (,): http://www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/
您可能想在在的 RFC 6266 和外观= “http://greenbytes.de/tech/tc2231/” 相对= “nofollow”> http://greenbytes.de/tech/tc2231/ 。
有关我此解决了这个问题:
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(data)
};
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = "foo-ä-€.html"
};
当我看广告在Fiddler中repsonse我可以看到的文件名已经automaticcaly一直使用UTF-8编码:
使用文件名的Fiddler响应具有编码内容处置例如UTF-8
如果我们看一下内容处置头的值,我们可以看到这将是一样@Johannes格耶他的答案。唯一的区别是,我们并没有做编码ourselfs,该ContentDispositionHeaderValue类需要的照顾。
我用于在内容处理标头的测试用例: http://greenbytes.de/tech/ tc2231 / 由儒略雷什克提及。 关于ContentDispositionHeaderValue类信息可以在MSDN上找到。
有关Asp.Net核心(第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());
我真的使用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);