53

I have this piece of code:

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

When the file name is "a_b_c.doc" or "abc.doc" the name of the downloaded file is displayed correctly. However, when the file name is "a b c .doc" the name of the downloaded file is only "a".

How can we solve this?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Huy Than
  • 1,538
  • 2
  • 16
  • 31

4 Answers4

89

Use quotes:

resp.addHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
Moritz Petersen
  • 12,902
  • 3
  • 38
  • 45
  • 1
    what if the filename has " in it ? (it is not possible in windows but linux files may have '"' in their name.) – Bor691 Mar 09 '14 at 16:56
  • 4
    This is THE correct way (filename value as quoted string) according to HTTP 1.1 spec: https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1 – betatester07 Jun 01 '16 at 17:10
17

According to the HTTP standard you surround the string with double-quotes, and escape any quotes or backslashes within by preceding them with a single backslash.

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

This will prompt to save as Very "interesting" file \ files.txt. Note that the presence of a backslash does not suggest a folder, it suggests the backslash is part of the filename (which is perfectly valid on Linux and some other platforms, but not on Windows.)

Community
  • 1
  • 1
Malvineous
  • 25,144
  • 16
  • 116
  • 151
2

Following steps are required:

  • URI-encode the filename
  • Replace the spaces in the encoded filename (we're using an URL encoder instead of URI encoder, but URL encoding uses + as encoded space instead of %20, so we need to manually replace them with %20).
  • Set the encoded file name in the header. Here we have two variants: one which specifices the encoding, and one that doesn't. For maximal compatibility we can specify both.

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

Example header: inline; filename*=UTF-8''Hello%20World.doc; filename=Hello%20World.doc

Successfully tested with

  • Firefox ✔
  • Chrome ✔
  • Edge ✔
  • Internet Explorer ✔
Peter Walser
  • 15,208
  • 4
  • 51
  • 78
  • unfortunately, doesn't work in Safari properly. You have to only have filename* or pass utf-8 name in plain `filename` part for Safari only – Alexander Goldabin Nov 10 '20 at 11:40
0

if you quote your filename with chr(34) it will work:

resp.addHeader("Content-Disposition", "inline; filename=" + chr(34) + fileName + chr(34));
tompave
  • 11,952
  • 7
  • 37
  • 63
Raphaël
  • 9
  • 1
  • 1
    `chr(34)` is there in PHP but this is a Java question and this does not work in Java. In Java, you would need to do `(char) 34` instead. But come on guys, this code is not readable unless you have the ASCII table in your head. Why not just use double quotes when you need double quotes? Of course, you need to escape them, i.e. put a backslash in front of it like in `"this is my \"quoted\" string"`. This is more readable and works the same in Java, PHP, C++, ... – Christopher K. Sep 06 '18 at 09:43