Unicode in Content-Disposition header

2020-01-29 10:20发布

I am using HttpContext object implemented in HttpHandler child to download a file, when I have non-ascii characters in file name it looks weird in IE whereas it looks fine in Firefox.

below is the code:-

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

when I supply 'ß' 'ä' 'ö' 'ü' 'ó' 'ß' 'ä' 'ö' 'ü' 'ó' in file name field it looks different than what I have in file name it looks fine in firefox. adding EncodingType and charset has been of no use.

In ie it is 'ß''ä''ö''ü''ó''ß''ä''ö''ü'_'ó' and in firefox it is 'ß' 'ä' 'ö' 'ü' 'ó' 'ß' 'ä' 'ö' 'ü' 'ó'.

Any Idea how this can be fixed?

7条回答
可以哭但决不认输i
2楼-- · 2020-01-29 10:30

I`m using Uri.EscapeUriString for converts all characters to their hexadecimal representation, and string.Normalize for Unicode normalization form C. (tested in ASP.NET MVC5 framework 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);
查看更多
forever°为你锁心
3楼-- · 2020-01-29 10:31

For me this solution is working on all major browsers:

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);

Using ASP.NET MVC 3.

The Replace is necessary, because Chrome doesn't like Comma (,) in parameter values: http://www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/

查看更多
趁早两清
4楼-- · 2020-01-29 10:33

For Asp.Net Core (version 2 as of this post) UrlPathEncode is deprecated, here's how to achieve the desired result:

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());
查看更多
戒情不戒烟
5楼-- · 2020-01-29 10:36

You may want to read RFC 6266 and look at the tests at http://greenbytes.de/tech/tc2231/.

查看更多
beautiful°
6楼-- · 2020-01-29 10:38

HttpUtility.UrlPathEncode might be a better option. As URLEncode will replace spaces with '+' signs.

查看更多
够拽才男人
7楼-- · 2020-01-29 10:48

I had similar problem. You have to use HttpUtility.UrlEncode or Server.UrlEncode to encode filename. Also I remember firefox didn't need it. Moreoverit ruined filename when it's url-encoded. My code:

// 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);

Edit

I have read specification more carefully. First of all RFC2183 states that:

Current [RFC 2045] grammar restricts parameter values (and hence Content-Disposition filenames) to US-ASCII.

But then I found references that [RFC 2045] is absolete and one must reference RFC 2231, which states:

Asterisks ("*") are reused to provide the indicator that language and character set information is present and encoding is being used. A single quote ("'") is used to delimit the character set and language information at the beginning of the parameter value. Percent signs ("%") are used as the encoding flag, which agrees with RFC 2047.

Which means that you can use UrlEncode for non-ascii symbols, as long as you include the encoding as stated in the rfc. Here is an example:

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

Note that filename is included in addition to filename* for backwards compatibility. You can also choose another encoding and modify the parameter accordingly, but UTF-8 covers everything.

查看更多
登录 后发表回答