Content-Disposition标头中的Unicode

问题描述 投票:10回答:6

我正在使用在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一直没用。

在它里面它是''','''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''

任何想法如何解决这个问题?

c# .net http-headers content-disposition
6个回答
16
投票

我有类似的问题。你必须使用HttpUtility.UrlEncodeServer.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一致。

这意味着您可以将UrlEncode用于非ascii符号,只要您包含rfc中所述的编码即可。这是一个例子:

string.Format("attachment; filename=\"{0}\"; filename*=UTF-8''{0}", Server.UrlEncode(fileName, Encoding.UTF8));

请注意,除了filename之外,filename*也包含在内,以实现向后兼容性。您也可以选择其他编码并相应地修改参数,但UTF-8涵盖了所有内容。


7
投票

HttpUtility.UrlPathEncode可能是更好的选择。由于URLEncode将用'+'符号替换空格。


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/


2
投票

您可能想阅读RFC 6266并查看http://greenbytes.de/tech/tc2231/的测试。


1
投票

对我来说,这解决了这个问题:

var result = new HttpResponseMessage(HttpStatusCode.OK)
{
   Content = new ByteArrayContent(data)
};

result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileNameStar = "foo-ä-€.html"
};

当我在fiddler中查看广告时,我可以看到文件名已经使用UTF-8自动编码:

Fiddler response example with encoded Content-Disposition filename using UTF-8

如果我们查看Content-Disposition标头的值,我们可以看到它与@Johannes Geyer的答案相同。唯一的区别是我们没有必要自己进行编码,ContentDispositionHeaderValue类负责处理。

我在Julian Reschke提到的qazxsw poi上使用了测试用例的Content-Disposition标题。有关ContentDispositionHeaderValue类的信息可以在MSDN上找到。


0
投票

对于Asp.Net Core(本文第2版)UrlPathEncode已弃用,以下是如何实现所需结果:

http://greenbytes.de/tech/tc2231/
© www.soinside.com 2019 - 2024. All rights reserved.