By Atif Aziz


2008-09-18 15:25:07 8 Comments

Web applications that want to force a resource to be downloaded rather than directly rendered in a Web browser issue a Content-Disposition header in the HTTP response of the form:

Content-Disposition: attachment; filename=FILENAME

The filename parameter can be used to suggest a name for the file into which the resource is downloaded by the browser. RFC 2183 (Content-Disposition), however, states in section 2.3 (The Filename Parameter) that the file name can only use US-ASCII characters:

Current [RFC 2045] grammar restricts parameter values (and hence Content-Disposition filenames) to US-ASCII. We recognize the great desirability of allowing arbitrary character sets in filenames, but it is beyond the scope of this document to define the necessary mechanisms.

There is empirical evidence, nevertheless, that most popular Web browsers today seem to permit non-US-ASCII characters yet (for the lack of a standard) disagree on the encoding scheme and character set specification of the file name. Question is then, what are the various schemes and encodings employed by the popular browsers if the file name “naïvefile” (without quotes and where the third letter is U+00EF) needed to be encoded into the Content-Disposition header?

For the purpose of this question, popular browsers being:

  • Firefox
  • Internet Explorer
  • Safari
  • Google Chrome
  • Opera

18 comments

@luchaninov 2019-07-22 13:58:45

PHP framework Symfony 4 has $filenameFallback in HeaderUtils::makeDisposition. You can look into this function for details - it is similar to the answers above.

Usage example:

$filenameFallback = preg_replace('#^.*\.#', md5($filename) . '.', $filename);
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename, $filenameFallback);
$response->headers->set('Content-Disposition', $disposition);

@Dmitry Kaigorodov 2015-07-10 15:01:51

Put the file name in double quotes. Solved the problem for me. Like this:

Content-Disposition: attachment; filename="My Report.doc"

http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download

I've tested multiple options. Browsers do not support the specs and act differently, I believe double quotes is the best option.

@Oskar Berggren 2016-02-25 16:35:22

Different problem though...

@Luca Steeb 2016-03-06 18:24:27

This sadly doesn't solve all problems explained in the answers above.

@Don Cheadle 2016-08-26 17:17:19

This will allow you to return a file name with spaces, &, %, # etc. So it solves that.

@Christophe Roussy 2018-09-19 13:55:34

What if the filename contains double quotes (yes this can happen), As specified in RFC 6266, the filename is a "quoted-string", and as specified in RFC 2616 double quotes within a quoted-string should be escaped with a backslash.

@user1664043 2019-03-13 19:18:16

Just an update since I was trying all this stuff today in response to a customer issue

  • With the exception of Safari configured for Japanese, all browsers our customer tested worked best with filename=text.pdf - where text is a customer value serialized by ASP.Net/IIS in utf-8 without url encoding. For some reason, Safari configured for English would accept and properly save a file with utf-8 Japanese name but that same browser configured for Japanese would save the file with the utf-8 chars uninterpreted. All other browsers tested seemed to work best/fine (regardless of language configuration) with the filename utf-8 encoded without url encoding.
  • I could not find a single browser implementing Rfc5987/8187 at all. I tested with the latest Chrome, Firefox builds plus IE 11 and Edge. I tried setting the header with just filename*=utf-8''texturlencoded.pdf, setting it with both filename=text.pdf; filename*=utf-8''texturlencoded.pdf. Not one feature of Rfc5987/8187 appeared to be getting processed correctly in any of the above.

@Martin Ørding-Thomsen 2011-07-19 10:34:35

I know this is an old post but it is still very relevant. I have found that modern browsers support rfc5987, which allows utf-8 encoding, percentage encoded (url-encoded). Then Naïve file.txt becomes:

Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt

Safari (5) does not support this. Instead you should use the Safari standard of writing the file name directly in your utf-8 encoded header:

Content-Disposition: attachment; filename=Naïve file.txt

IE8 and older don't support it either and you need to use the IE standard of utf-8 encoding, percentage encoded:

Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt

In ASP.Net I use the following code:

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.Browser.Browser == "Safari")
    contentDisposition = "attachment; filename=" + fileName;
else
    contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

I tested the above using IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.

Update November 2013:

Here is the code I currently use. I still have to support IE8, so I cannot get rid of the first part. It turns out that browsers on Android use the built in Android download manager and it cannot reliably parse file names in the standard way.

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
    contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\"";
else
    contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

The above now tested in IE7-11, Chrome 32, Opera 12, FF25, Safari 6, using this filename for download: 你好abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§!#¤%&()=`@£$€{[]}+´¨^~'-_,;.txt

On IE7 it works for some characters but not all. But who cares about IE7 nowadays?

This is the function I use to generate safe file names for Android. Note that I don't know which characters are supported on Android but that I have tested that these work for sure:

private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
    char[] newFileName = fileName.ToCharArray();
    for (int i = 0; i < newFileName.Length; i++)
    {
        if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
            newFileName[i] = '_';
    }
    return new string(newFileName);
}

@TomZ: I tested in IE7 and IE8 and it turned out that I did not need to escape apostrophe ('). Do you have an example where it fails?

@Dave Van den Eynde: Combining the two file names on one line as according to RFC6266 works except for Android and IE7+8 and I have updated the code to reflect this. Thank you for the suggestion.

@Thilo: No idea about GoodReader or any other non-browser. You might have some luck using the Android approach.

@Alex Zhukovskiy: I don't know why but as discussed on Connect it doesn't seem to work terribly well.

@Arantor 2011-11-14 23:01:46

It no longer works in Firefox 8.

@Martin Ørding-Thomsen 2011-11-23 08:48:28

I tested the above code using FF 8.0.1 on Windows 7. RFC5987 is chosen and the file name (Naïve file.txt) is shown correctly.

@Thilo 2012-03-08 08:15:16

Got it working for Mobile Safari (raw utf-8 as suggested above), but that does not work for GoodReader from the same device. Any ideas?

@TomZ 2012-06-19 18:55:31

IE7 and 8 also need apostrophes escaped: .Replace("'", Uri.HexEscape('\''))

@Martin Tournoij 2013-01-21 14:40:20

Directly writing UTF-8 characters seems to work for current versions of Firefox, Chrome, and Opera. Didn't test Safari & IE.

@ASBai 2013-04-25 20:24:05

My Chrome '26.0.1410.64 m' doesn't recognize the rfc5987 format. It eat the old ie percentage encoding.

@Dave Van den Eynde 2013-11-08 14:02:04

Why not combine them, as Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt and skip the browser sniffing? Would that work?

@Eric F. 2013-12-24 06:50:07

Tested on Chrome 31.0, IE11, FF26 all work!

@robinst 2014-07-11 09:23:00

Another addition: In IE9, the %20 in a filename* argument does not result in a space, but a literal %20 in the file name.

@Rutix 2015-03-02 16:13:51

@robinst If %20 doesn't work what did you use then?

@robinst 2015-03-03 03:13:20

@Rutix In my case, removing the filename part altogether worked, because the path of the URL already included the file name. All the tested browsers then used that as the file name (which worked with spaces).

@oakman 2015-04-25 07:46:35

Tested on IE11 Mobile on "Windows Phone 8.1 Update" did not work :-(

@Georg 2015-06-03 07:56:20

@DaveVandenEynde This is not warking in modern Chromium based browsers. Browser show a warning about security problems instead (I'm not sure which security problems can be caused by multiple filename specification, though).

@Dave Van den Eynde 2015-06-04 12:33:40

@Georg I've since learned to rely on Web.Api's ContentDispositionHeaderValue class to deal with this for me.

@Christopher Schultz 2015-12-03 17:44:15

Some resent testing of this (using inline;filename=) suggests that using filenames containing spaces must have surrounding double-quote (") characters for Firefox 42 to use anything other than the filename before the first space. Using URL-encoded filenames does not work; the filename in the "Save As" dialog becomes my%20file.txt. Same with Safari 9: quotes must be used and %-encoding is a mess. Google Chrome 46 seems to ignore the header altogether, or possibly it doesn't like something specific about the formatting.

@Christopher Schultz 2015-12-03 18:05:06

I should have mentioned that URL-encoding does not work with filename specifically. Use of filename* is another matter. Also note that you can't use + for space in the filename when using filename*: you must use %20.

@gdibble 2016-05-17 18:10:09

In Node.js with hapi for instance, you can reply(something).header('Content-Disposition', 'attachment; filename="' + encodeURI(fileName) + '"')

@wullinkm 2016-08-26 09:47:47

The kind folks at fastmail found another workaround: blog.fastmail.com/2011/06/24/download-non-english-filenames Content-Disposition: attachment; filename="foo-%c3%a4.html"; filename*=UTF-8''foo-%c3%a4.html Specifying the fileName twice (one time without the UTF-8 prefix and one time with) makes it work in IE8-11, Edge, Chrome, Firefox and Safari (seems like apple fixed safari, so it works there as well now)

@Alex Zhukovskiy 2016-09-12 12:48:31

@MartinØrding-Thomsen Do you know why standard System.Net.Mime.ContentDisposition generates invalid name which cannot be interpreted by any browser (even chrome cannot)?

@starmandeluxe 2017-05-04 06:14:07

This is the correct answer.

@Brice 2018-03-12 14:46:39

@DaveVandenEynde One must distinguish the Content-Disposition in the request headers from those in the a multipart/form-data body, In the later case using filename* is explicitly disallowed for Content-Disposition, see tools.ietf.org/html/rfc7578#section-4.2.

@Lankymart 2016-05-23 12:17:58

Classic ASP Solution

Most modern browsers support passing the Filename as UTF-8 now but as was the case with a File Upload solution I use that was based on FreeASPUpload.Net (site no longer exists, link points to archive.org) it wouldn't work as the parsing of the binary relied on reading single byte ASCII encoded strings, which worked fine when you passed UTF-8 encoded data until you get to characters ASCII doesn't support.

However I was able to find a solution to get the code to read and parse the binary as UTF-8.

Public Function BytesToString(bytes)    'UTF-8..
  Dim bslen
  Dim i, k , N 
  Dim b , count 
  Dim str

  bslen = LenB(bytes)
  str=""

  i = 0
  Do While i < bslen
    b = AscB(MidB(bytes,i+1,1))

    If (b And &HFC) = &HFC Then
      count = 6
      N = b And &H1
    ElseIf (b And &HF8) = &HF8 Then
      count = 5
      N = b And &H3
    ElseIf (b And &HF0) = &HF0 Then
      count = 4
      N = b And &H7
    ElseIf (b And &HE0) = &HE0 Then
      count = 3
      N = b And &HF
    ElseIf (b And &HC0) = &HC0 Then
      count = 2
      N = b And &H1F
    Else
      count = 1
      str = str & Chr(b)
    End If

    If i + count - 1 > bslen Then
      str = str&"?"
      Exit Do
    End If

    If count>1 then
      For k = 1 To count - 1
        b = AscB(MidB(bytes,i+k+1,1))
        N = N * &H40 + (b And &H3F)
      Next
      str = str & ChrW(N)
    End If
    i = i + count
  Loop

  BytesToString = str
End Function

Credit goes to Pure ASP File Upload by implementing the BytesToString() function from include_aspuploader.asp in my own code I was able to get UTF-8 filenames working.


Useful Links

@Gustav 2016-05-20 12:47:05

In PHP this did it for me (assuming the filename is UTF8 encoded):

header('Content-Disposition: attachment;'
    . 'filename="' . addslashes(utf8_decode($filename)) . '";'
    . 'filename*=utf-8\'\'' . rawurlencode($filename));

Tested against IE8-11, Firefox and Chrome.
If the browser can interpret filename*=utf-8 it will use the UTF8 version of the filename, else it will use the decoded filename. If your filename contains characters that can't be represented in ISO-8859-1 you might want to consider using iconv instead.

@Toby Speight 2016-05-20 14:32:32

Although this code may answer the question, providing additional context regarding why and/or how it answers the question would significantly improve its long-term value. Please edit your answer to add some explanation.

@Gustav 2016-05-22 15:20:42

Whoa, none of the above code-only answers got downvoted or critized like that. Also I found the why was answered well enough already: IE does not interpret filename*=utf-8 but needs ISO8859-1 version of the filename, which this script does offer. Only wanted to give the lazy a working simple code for PHP.

@j4k3 2016-06-28 06:49:13

I think this got downvoted because the question isn't language specific but about the what RFCs to stick to when implementing the header encoding. Thanks however, for this answer, for PHP, this code made my woes go away.

@Lyndsy Simon 2016-07-07 14:43:31

Thank you. This answer may not have strictly answered the question, but it was exactly what I was looking for and helped me resolve the issue in Python.

@Antti Haapala 2016-09-11 21:35:38

I am pretty sure this code can be used as an attack vector if the user can control the name of the file.

@Emanuele Spatola 2015-09-25 12:45:11

If you are using a nodejs backend you can use the following code I found here

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" 
             + encodeRFC5987ValueChars(fileName);

function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            // so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

@gdibble 2016-05-17 18:13:50

Better to use encodeURI(str). As example with dates in the file name: encodeURIComponent('"Kornél Kovács 1/1/2016') => "Kornél Kovács 1%2F1%2F2016" vs. encodeURI('"Kornél Kovács 1/1/2016') => "Kornél Kovács 1/1/2016"

@martinoss 2015-06-25 08:10:39

In ASP.NET Web API, I url encode the filename:

public static class HttpRequestMessageExtensions
{
    public static HttpResponseMessage CreateFileResponse(this HttpRequestMessage request, byte[] data, string filename, string mediaType)
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream(data);
        stream.Position = 0;

        response.Content = new StreamContent(stream);

        response.Content.Headers.ContentType = 
            new MediaTypeHeaderValue(mediaType);

        // URL-Encode filename
        // Fixes behavior in IE, that filenames with non US-ASCII characters
        // stay correct (not "_utf-8_.......=_=").
        var encodedFilename = HttpUtility.UrlEncode(filename, Encoding.UTF8);

        response.Content.Headers.ContentDisposition =
            new ContentDispositionHeaderValue("attachment") { FileName = encodedFilename };
        return response;
    }
}

IE 9 Not fixed
IE 9 Fixed

@renergy 2015-04-05 15:45:29

I ended up with the following code in my "download.php" script (based on this blogpost and these test cases).

$il1_filename = utf8_decode($filename);
$to_underscore = "\"\\#*;:|<>/?";
$safe_filename = strtr($il1_filename, $to_underscore, str_repeat("_", strlen($to_underscore)));

header("Content-Disposition: attachment; filename=\"$safe_filename\""
.( $safe_filename === $filename ? "" : "; filename*=UTF-8''".rawurlencode($filename) ));

This uses the standard way of filename="..." as long as there are only iso-latin1 and "safe" characters used; if not, it adds the filename*=UTF-8'' url-encoded way. According to this specific test case, it should work from MSIE9 up, and on recent FF, Chrome, Safari; on lower MSIE version, it should offer filename containing the ISO8859-1 version of the filename, with underscores on characters not in this encoding.

Final note: the max. size for each header field is 8190 bytes on apache. UTF-8 can be up to four bytes per character; after rawurlencode, it is x3 = 12 bytes per one character. Pretty inefficient, but it should still be theoretically possible to have more than 600 "smiles" %F0%9F%98%81 in the filename.

@renergy 2015-04-05 16:13:46

...but the max transferrable filename length also depends on the client. Just found out that at most [89 smiles😁].pdf filename gets through MSIE11. In Firefox37, it is at most [111x 😁].pdf. Chrome41 truncates the filename at 110th smile. Interestingly, the suffix is transferred ok.

@Andrei I 2015-01-27 11:54:13

We had a similar problem in a web application, and ended up by reading the filename from the HTML <input type="file">, and setting that in the url-encoded form in a new HTML <input type="hidden">. Of course we had to remove the path like "C:\fakepath\" that is returned by some browsers.

Of course this does not directly answer OPs question, but may be a solution for others.

@Oskar Berggren 2016-02-25 16:38:58

Completely different issue. The question is about downloading, your reply is about uploading.

@Vasilen Donchev 2013-04-19 11:29:24

I use the following code snippets for encoding (assuming fileName contains the filename and extension of the file, i.e.: test.txt):


PHP:

if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
     header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $fileName ) . '"' );
}
else
{
     header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $fileName ) );
}

Java:

fileName = request.getHeader ( "user-agent" ).contains ( "MSIE" ) ? URLEncoder.encode ( fileName, "utf-8") : MimeUtility.encodeWord ( fileName );
response.setHeader ( "Content-disposition", "attachment; filename=\"" + fileName + "\"");

@mpen 2013-09-17 23:46:41

You sure it's not supposed to be rawurlencode in PHP?

@Brett Zamir 2014-02-01 13:06:32

Right, it should be rawurlencode in PHP at least for the filename*= disposition header since value-chars used in ext-value of RFC 6266->RFC 5987 (see tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section-3.2.1 ) doesn't allow space without percent escaping (filename=, on the other hand, seems that it could allow a space without escaping at all though only ASCII should be present here). It isn't necessary to encode with the full strictness of rawurlencode, so a few characters can be unescaped: gist.github.com/brettz9/8752120

@Kornel 2008-10-19 18:26:36

There is a simple and very robust alternative: use a URL that contains the filename you want.

When the name after the last slash is the one you want, you don't need any extra headers!

This trick works:

/real_script.php/fake_filename.doc

And if your server supports URL rewriting (e.g. mod_rewrite in Apache) then you can fully hide the script part.

Characters in URLs should be in UTF-8, urlencoded byte-by-byte:

/mot%C3%B6rhead   # motörhead

@Sean Hanley 2009-12-31 17:24:37

Anyone know how to do this in ASP.NET? Would it be possible to do something like GetAttachment.aspx?id=34/fake_filename.doc without a lot of trouble?

@Kornel 2009-12-31 21:24:17

Try GetAttachment.aspx/fake_filename.doc?id=34 (although it might be Apache-only quirk)

@David 2010-07-15 15:13:17

You can handle this kind of path in IIS by using either a custom .Net HttpModule or maybe the UrlRewrite option in IIS7.

@kristopolous 2011-09-14 20:24:17

this is a fantastic solution; really helped me a lot. thanks.

@BerggreenDK 2012-08-10 20:21:53

@SeanHanley - also check out URL rewrite for IIS and MVC framework

@mpen 2013-09-19 17:24:48

I went down the rabbit trail and tried some of the other solutions; trying to sniff out the correct browser and version to set the headers correctly is too much of a nightmare. Chrome was incorrectly identifying as Safari which does not behave the same at all (breaks on commas if not encoded correctly). Save yourself the trouble, use this solution and alias the URL as needed.

@Piper 2014-04-03 13:00:07

I did this in ASP.NET 4.0 web forms using ASP.NET Routing. I registered the route: routes.MapPageRoute("Download", "download/{id}/{filename}", "~/download.aspx"); In download.aspx I only use the id: Page.RouteData.Values["id"] and do not write the extra header "Content-Disposition". Works nicely and is easier than HttpModule I suppose.

@bronze man 2014-12-04 05:20:36

please do not encode . to %2e ,ie7 in winxp will fail to show correct file name.

@Luca Steeb 2015-11-15 01:32:38

The /:id/:filename method is really simple and works, thank you!

@alex 2016-03-18 20:52:17

how should i implement url approach with laravel Response::download()?if i dont define file name in this method it will select file name itself and doesn't consider url

@Julik 2016-05-29 20:09:56

A thousand times "Yes". You will seriously win time with this. More even - some Android browsers will flat out ignore the Content-Disposition and create very interesting filenames instead (they will be generated from your path). So the only solution for keeping one's sanity is just setting Content-Disposition: attachment and passing the desired filename as the last path component:

@Caleb Hearon 2016-08-02 19:10:22

this is a great solution (and made me feel kinda stupid) on a related note, remember if the filename comes from a user variable you still have to make sure it's ready for the filesystem. If you don't, and the file has something like /, you get really weird browser errors. With this answer as a reference I used s.replace(/[\000-\031\\\/:*?"<>\|]/g, '_')

@Guney Ozsan 2019-02-22 09:23:43

So cool, but how come this works?

@Guney Ozsan 2019-02-22 09:27:20

But in this case we need to know the file name in advance, right? That makes two requests, one for the file name, one for the file itself.

@Kornel 2019-02-24 16:30:40

@GuneyOzsan On the HTTP level there's absolutely no difference, and it never causes any extra requests. You don't need to know the filename, you need to include the filename in the URL which you have to know anyway.

@Guney Ozsan 2019-02-26 12:45:03

@Kornel in my current project I don't know file names in advance and request files by ID and try to get the file (as stream) and name (preferably in header) in a single request. On the other hand the C# version that Unity uses does not support that weird syntax in Content-Disposition. Eventually I resolved it by encoding it in php with filename="' . rawurlencode($file_name_with_extension) . '", and decoding it in C# using headerValue = ContentDispositionHeaderValue.Parse(contentDisposition), and fileName = Uri.UnescapeDataString(headerValue.FileName.Replace("\"", "")).

@Guney Ozsan 2019-02-26 12:46:37

@Kornel I was actually wondering how or why fake_filename.doc is interpreted as if it is the file name in header.

@Kornel 2019-02-26 18:19:50

@GuneyOzsan the filename for saving is deduced by the web browser, and browsers have no understanding of what is happening server side, so they don't understand and don't care how the server interprets the URL. Browsers just take whatever is after the last slash in the URL path, sometimes additionally trying to correct filename extensions based on Content-Type.

@Guney Ozsan 2019-02-26 21:51:37

@Kornel Ops, sorry, I was tired working for hours to resolve some bug and confused 'slash' with 'underscore' trying to understand the black magic behind why browser strips the part fake_. Thank you for your time.

@MvG 2014-01-05 12:48:27

RFC 6266 describes the “Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)”. Quoting from that:

6. Internationalization Considerations

The “filename*” parameter (Section 4.3), using the encoding defined in [RFC5987], allows the server to transmit characters outside the ISO-8859-1 character set, and also to optionally specify the language in use.

And in their examples section:

This example is the same as the one above, but adding the "filename" parameter for compatibility with user agents not implementing RFC 5987:

Content-Disposition: attachment;
                     filename="EURO rates";
                     filename*=utf-8''%e2%82%ac%20rates

Note: Those user agents that do not support the RFC 5987 encoding ignore “filename*” when it occurs after “filename”.

In Appendix D there is also a long list of suggestions to increase interoperability. It also points at a site which compares implementations. Current all-pass tests suitable for common file names include:

  • attwithisofnplain: plain ISO-8859-1 file name with double quotes and without encoding. This requires a file name which is all ISO-8859-1 and does not contain percent signs, at least not in front of hex digits.
  • attfnboth: two parameters in the order described above. Should work for most file names on most browsers, although IE8 will use the “filename” parameter.

That RFC 5987 in turn references RFC 2231, which describes the actual format. 2231 is primarily for mail, and 5987 tells us what parts may be used for HTTP headers as well. Don't confuse this with MIME headers used inside a multipart/form-data HTTP body, which is governed by RFC 2388 (section 4.4 in particular) and the HTML 5 draft.

@evtuhovdo 2016-07-15 10:14:13

I had trouble in Safari . When downloading files with Russian names received erroneous and unreadable characters . The solution has helped . But we need to send a header in a single row ( !!! ) .

@Albert Tobac 2018-03-07 12:52:11

the best answer! thanks

@Jim 2008-09-18 15:39:58

There is discussion of this, including links to browser testing and backwards compatibility, in the proposed RFC 5987, "Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters."

RFC 2183 indicates that such headers should be encoded according to RFC 2184, which was obsoleted by RFC 2231, covered by the draft RFC above.

@lapo 2011-02-16 16:22:31

With a quick test, that is implemented by Firefox and horribly broken in IE: it just doesn't recognize "filename*" as a filename and tries to desume the filename from mime-type and last part of the URL.

@Julian Reschke 2011-09-09 15:28:56

This was partly fixed in IE9.

@Julian Reschke 2011-09-29 15:46:47

Also note that the internet draft (not "draft RFC") has been finished, and the final document is RFC 5987 (greenbytes.de/tech/webdav/rfc5987.html)

@catchdave 2012-01-11 00:09:56

Related to this, I discovered that Firefox (versions 4-9 inclusive) break if there is a comma (,) in the filename, e.g. Content-Disposition: filename="foo, bar.pdf". The result is that firefox downloads the file correctly but keeps the .part extension (e.g foo,bar.pdf-1.part). Then, of course the file won't open correctly because the application is not associated with .part. Other ASCII chars seem to work OK.

@Dennis C 2013-09-13 02:16:26

The RFC is well known being "not implemented correctly" by different browsers. IE, Chrome, Fx, especially Android stock browser handle very difference in Unicode/non-ascii charset.

@Matthew Schinckel 2013-10-07 23:03:27

@DennisCheung Do you have a reference for these inconsistencies in browser handling? (I want to provide evidence for an issue).

@Dennis C 2013-10-08 01:19:34

@EricLaw 2013-10-21 04:26:01

For more about IE behavior, see blogs.msdn.com/b/ieinternals/archive/2010/06/07/…

@Christoffer Hammarström 2014-12-04 09:47:01

@catchdave: You forgot the "attachment;" part.

@gdibble 2016-05-17 18:11:04

In Node.js with hapi for instance, you can reply(something).header('Content-Disposition', 'attachment; filename="' + encodeURI(fileName) + '"')

@Antti Haapala 2016-09-11 21:33:36

All in all, this is nothing but a link-only answer with 74 upvotes.

@Stano 2012-05-31 15:48:11

I tested the following code in all major browsers, including older Explorers (via the compatibility mode), and it works well everywhere:

$filename = $_GET['file']; //this string from $_GET is already decoded
if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE"))
  $filename = rawurlencode($filename);
header('Content-Disposition: attachment; filename="'.$filename.'"');

@Elmer 2010-07-15 15:08:29

in asp.net mvc2 i use something like this:

return File(
    tempFile
    , "application/octet-stream"
    , HttpUtility.UrlPathEncode(fileName)
    );

I guess if you don't use mvc(2) you could just encode the filename using

HttpUtility.UrlPathEncode(fileName)

@Serge Wautier 2011-03-14 09:24:01

Problem solved, dev happy :-)

@SerialSeb 2011-04-28 16:14:01

Url encoding for file name encoding is not valid, browsers ought to not url decode those.

@pseudocoder 2015-06-16 15:50:36

IE 11 definitely does not decode url encoding in this field.

@Reza 2016-03-09 18:43:51

But it needed to be UrlEncoded when the browser is Chrome or IE, others such as FF, Safari and Opera work fine with out encoding

@Atif Aziz 2008-09-18 16:08:16

The following document linked from the draft RFC mentioned by Jim in his answer further addresses the question and definitely worth a direct note here:

Test Cases for HTTP Content-Disposition header and RFC 2231/2047 Encoding

@Pablo Montilla 2012-07-10 20:43:46

Note that one can supply both ways of encoding the filename parameter, and that they appear to work correctly with old browsers and new browsers (old being MSIE8 and Safari in this case). Check attfnboth in the report mentioned by @AtifAziz.

@Dario Solera 2008-09-18 15:28:29

I normally URL-encode (with %xx) the filenames, and it seems to work in all browsers. You might want to do some tests anyway.

@Atif Aziz 2008-09-18 15:31:43

I did test in a few and it does not work that way in all the browsers, thus the question. :)

Related Questions

Sponsored Content

6 Answered Questions

[SOLVED] Are HTTP headers case-sensitive?

  • 2011-03-10 11:22:16
  • Svish
  • 168528 View
  • 615 Score
  • 6 Answer
  • Tags:   http http-headers

6 Answered Questions

[SOLVED] application/x-www-form-urlencoded or multipart/form-data?

9 Answered Questions

[SOLVED] How to send a header using a HTTP request through a curl call?

  • 2008-12-10 16:38:57
  • gagneet
  • 1451202 View
  • 1290 Score
  • 9 Answer
  • Tags:   curl http-headers

12 Answered Questions

[SOLVED] What does <meta http-equiv="X-UA-Compatible" content="IE=edge"> do?

6 Answered Questions

[SOLVED] View HTTP headers in Google Chrome?

6 Answered Questions

[SOLVED] Custom HTTP headers : naming conventions

  • 2010-08-24 21:59:38
  • Julien Genestoux
  • 331096 View
  • 1026 Score
  • 6 Answer
  • Tags:   http http-headers

1 Answered Questions

0 Answered Questions

PHP Content-Disposition header: Specialcharacters in the filename

1 Answered Questions

[SOLVED] Special Characters in Content-Disposition filename

1 Answered Questions

Sponsored Content