繁体   English   中英

Content-Disposition 标头中的 Unicode

[英]Unicode in Content-Disposition header

我正在使用在 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 中它是 'ß' ' ä' 'ö' 'ü' 'ó' 'ß' 'ä' 'ö' 'ü' 'ó'。

知道如何解决这个问题吗?

我有类似的问题。 您必须使用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 涵盖了所有内容。

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。

替换是必要的,因为 Chrome 不喜欢参数值中的逗号 (,): http : //www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/

您可能需要阅读RFC 6266并查看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 中的响应时,我可以看到文件名已使用 UTF-8 自动编码:

使用 UTF-8 编码的 Content-Disposition 文件名的 Fiddler 响应示例

如果我们查看 Content-Disposition 标头的值,我们会发现它与 @Johannes Geyer 的回答相同。 唯一的区别是我们不必自己进行编码,ContentDispositionHeaderValue 类会负责。

正如 Julian Reschke 所提到的,我在http://greenbytes.de/tech/tc2231/上使用了 Content-Disposition 标头的测试用例。 可以在 MSDN 上找到有关 ContentDispositionHeaderValue 类的信息。

对于 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());

我使用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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM