想要强制下载资源而不是直接在Web浏览器中呈现资源的Web应用程序在表单的HTTP响应中发出Content-Disposition报头:

Content-Disposition:附件;filename = filename

filename参数可用于建议浏览器将资源下载到的文件的名称。然而,RFC 2183 (Content-Disposition)在2.3节(文件名参数)中规定文件名只能使用US-ASCII字符:

当前[RFC 2045]语法限制 参数值(因此 内容-处置文件名)到 us - ascii。我们认可伟大的 允许任意的可取性 文件名中的字符集,但它是 超出了本文档的范围 定义必要的机制。

然而,有经验证据表明,目前大多数流行的Web浏览器似乎允许非us - ascii字符,但(由于缺乏标准)在文件名的编码方案和字符集规范上存在分歧。问题是,如果文件名“naïvefile”(不带引号,第三个字母是U+00EF)需要编码到Content-Disposition报头中,那么流行的浏览器采用了哪些不同的方案和编码?

为了解决这个问题,流行的浏览器是:

谷歌Chrome Safari Internet Explorer或Edge 火狐 歌剧


当前回答

我在所有主流浏览器中测试了以下代码,包括老式的explorer(通过兼容模式),它在任何地方都能正常工作:

$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.'"');

其他回答

在提议的RFC 5987“超文本传输协议(HTTP)报头字段参数的字符集和语言编码”中对此进行了讨论,包括浏览器测试和向后兼容性的链接。

RFC 2183表示这样的报头应该根据RFC 2184进行编码,RFC 2184已被RFC 2231废止,上面的RFC草案涵盖了这一点。

RFC 6266描述了“超文本传输协议(HTTP)中内容处理报头字段的使用”。引用其中的话:

6. 国际化的考虑 参数" filename* "(章节4.3),使用定义的编码 在[RFC5987]中,允许服务器传输外部的字符 ISO-8859-1字符集,也可以选择指定语言 在使用。

在例子部分:

这个示例与上面的示例相同,但添加了"filename" 参数,用于与未实现的用户代理的兼容性 RFC 5987: 附加:附件; 文件名= "欧元利率”; 文件名* = utf - 8”% e2 % 82% ac % 20率 注意:不支持RFC 5987编码的用户代理 当" filename "后面出现" filename* "时,忽略" filename* "。

在附录D中,还列出了一长串提高互操作性的建议。它还指向一个比较实现的站点。适用于常用文件名的当前全通过测试包括:

attwithisofnplain:普通的ISO-8859-1文件名,双引号,不带编码。这要求文件名完全符合ISO-8859-1,并且不包含百分号,至少在十六进制数字前面不包含百分号。 Attfnboth:上述顺序的两个参数。应该适用于大多数浏览器上的大多数文件名,尽管IE8将使用" filename "参数。

RFC 5987又引用了描述实际格式的RFC 2231。2231主要用于邮件,5987告诉我们哪些部分也可以用于HTTP报头。不要将其与多部分/form-data HTTP主体中使用的MIME头相混淆,后者受RFC 2388(特别是4.4节)和HTML 5草案的约束。

以下文件链接自Jim在回答中提到的RFC草案,进一步解决了这个问题,在这里值得直接注意:

HTTP内容处理头和rfc2231 /2047编码的测试用例

在ASP。NET Web API,我url编码的文件名:

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


我们在一个web应用程序中遇到了类似的问题,最后从HTML <input type="file">中读取文件名,并在一个新的HTML <input type="hidden">中以url编码的形式设置它。当然,我们必须删除一些浏览器返回的“C:\fakepath\”这样的路径。

当然,这并不能直接回答OPs的问题,但可能是其他人的解决方案。