11

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

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

4

7 回答 7

21

我有类似的问题。您必须使用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] 语法将参数值(以及因此的 Content-Disposition 文件名)限制为 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 涵盖了所有内容。

于 2010-03-30T08:27:39.827 回答
11

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

于 2013-05-03T19:14:43.473 回答
5

对我来说,这个解决方案适用于所有主要浏览器:

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/

于 2015-06-16T15:35:03.187 回答
2

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

于 2012-05-02T18:47:31.750 回答
2

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

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

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

当我查看提琴手中的响应时,我可以看到文件名已使用 UTF-8 自动编码:

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

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

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

于 2017-10-20T09:31:23.140 回答
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());
于 2018-04-25T21:41:48.707 回答
0

我正在使用Uri.EscapeUriStringfor 将所有字符转换为其十六进制表示形式,并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);
于 2019-07-31T12:48:38.380 回答