How to set filename containing spaces in Content-Disposition header

JavaServletsDownloadFilenames

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

Use quotes:

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

Solution 2 - Java

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

Solution 3 - Java

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 ✔

Solution 4 - Java

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHuy ThanView Question on Stackoverflow
Solution 1 - JavaMoritz PetersenView Answer on Stackoverflow
Solution 2 - JavaMalvineousView Answer on Stackoverflow
Solution 3 - JavaPeter WalserView Answer on Stackoverflow
Solution 4 - JavaRaphaëlView Answer on Stackoverflow