想要强制下载资源而不是直接在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 火狐 歌剧


当前回答

在PHP中,这为我做了(假设文件名是UTF8编码):

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

在IE8-11、Firefox和Chrome浏览器上进行测试。 如果浏览器可以解释文件名*=utf-8,它将使用文件名的UTF8版本,否则它将使用解码后的文件名。如果你的文件名包含的字符不能在ISO-8859-1中表示,你可能要考虑使用iconv代替。

其他回答

在asp.net mvc2中,我使用这样的东西:

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

我想如果你不使用mvc(2),你可以只编码文件名使用

HttpUtility.UrlPathEncode(fileName)

经典ASP解决方案

大多数现代浏览器现在都支持将文件名作为UTF-8传递,但我使用的文件上传解决方案是基于FreeASPUpload的。Net(站点已经不存在了,链接指向archive.org),它不会工作,因为二进制解析依赖于读取单字节ASCII编码的字符串,当您传递UTF-8编码的数据时,它工作得很好,直到您得到ASCII不支持的字符。

然而,我能够找到一个解决方案,使代码读取和解析二进制为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

通过在我自己的代码中实现include_aspuploader.asp中的by睾string()函数,我能够获得UTF-8文件名。


有用的链接

一个ASP经典应用程序中的Multipart/form-data和UTF-8 Unicode, UTF, ASCII, ANSI格式的差异

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

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

我在所有主流浏览器中测试了以下代码,包括老式的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.'"');

只是一个更新,因为我今天为了回应一个客户的问题而尝试了所有这些东西

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.