如何在Content-Disposition标头中设置含有空格的文件名

回答 4 浏览 2.6万 2013-09-05

我有这样一段代码:

resp.addHeader("Content-Disposition", "inline; filename=" + fileName);

当文件名为 "a_b_c.doc "或 "abc.doc "时,下载的文件名会正确显示。然而,当文件名是 "a b c .doc "时,下载的文件名只有 "a"。

我们怎样才能解决这个问题呢?

Huy Than 提问于2013-09-05
4 个回答
#1楼
得票数 87

使用引号:

resp.addHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
Moritz Petersen 提问于2013-09-05
如果文件名里有"怎么办?(这在windows系统中是不可能的,但linux系统的文件可能在其名称中含有'"'。)Bor691 2014-03-09
根据HTTP 1.1规范,这是正确的方式(文件名值为引号字符串):w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1betatester07 2016-06-01
#2楼
得票数 17

根据HTTP标准,你要用双引号包围这个字符串,并通过在其前面加一个反斜杠来转义任何引号或反斜杠。

Content-Disposition: attachment; filename="Very \"interesting\" file \\ files.txt"

这将提示保存为Very "interesting" file \ files.txt。请注意,反斜杠的出现并不表明是一个文件夹,它表明反斜杠是文件名的一部分(这在Linux和其他一些平台上是完全有效的,但在Windows上不是。)

Malvineous 提问于2016-07-12
Community 修改于2021-10-07
#3楼
得票数 2

需要采取以下步骤:

  • URI-encode的文件名
  • 替换编码文件名中的空格(我们使用的是URL编码器,而不是URI编码器,但是URL编码使用+作为编码空格,而不是%20,所以我们需要手动替换为%20)。
  • 在头文件中设置编码的文件名。这里我们有两种变体:一种是指定编码,另一种是不指定编码。为了达到最大的兼容性,我们可以同时指定这两种方式。

Code:

String fileName = ...;
String encodedFileName = URLEncoder.encode(fileName, 
    StandardCharsets.UTF_8.name()).replace("+", "%20");

response.setHeader("Content-Disposition", 
    String.format("inline; filename*=UTF-8''%1$s; filename=%1$s", encodedFileName));

头部示例:inline; filename*=UTF-8''Hello%20World.doc; filename=Hello%20World.doc

成功测试了

  • Firefox ✔
  • Chrome ✔
  • Edge ✔
  • Internet Explorer ✔
Peter Walser 提问于2019-07-24
Peter Walser 修改于2019-07-24
不幸的是,在Safari中不能正常工作。你必须只有文件名*或在Safari浏览器中传递utf-8名称的普通filename部分。Alexander Goldabin 2020-11-10
#4楼
得票数 0

如果你用chr(34)引用你的文件名,它就会起作用:

resp.addHeader("Content-Disposition", "inline; filename=" + chr(34) + fileName + chr(34));
Raphaël 提问于2015-07-29
tompave 修改于2015-07-29
chr(34)在PHP中是存在的,但这是一个Java问题,这在Java中不起作用。在Java中,你需要用(char) 34来代替。但拜托,除非你脑子里有ASCII表,否则这段代码是无法阅读的。为什么不在需要双引号的时候直接使用双引号呢?当然,你需要转义,即像"this is my \"quoted\" string"那样在前面加一个反斜杠。这样做更有可读性,而且在Java、PHP、C++中的效果都一样。Christopher K. 2018-09-06