[JAVA] How to download a file (Servlet, HTML, Apache, Tomcat)

We have summarized the settings for downloading files on the Web system by linking Tomcat and Apache. [Confirmed environment]

Environment at the time of confirmation

Download with Servlet

Set the content type to ʻapplication / octet-stream`

response.setContentType("application/octet-stream");
response.getWriter().write("Hello World");

https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types

This is the default value for binary format files. It actually represents an unknown binary format file, and the browser usually does not run it automatically or ask if it should run. They treat the value of the Content-Disposition header as if it were an attachment and suggest that the file be'save as'.

Set the value of the Content-Disposition header to ʻattachment`

As mentioned above, you can download it by specifying ʻapplication / octet-stream as the content type. However, if you know the type of file to download, it feels strange to specify ʻapplication / octet-stream.

As shown below, if you specify ʻattachment` in the Content-Disposition header, you can download even if the content type is not" application / octet-stream ".

response.setContentType("text/html");
response.setHeader("Content-Disposition","attachment");
response.getWriter().write("Hello World");

Default file name when downloading

The value specified for filename will be the default file name at the time of download.

response.setHeader("Content-Disposition","attachment;filename=\"sample.html\"");
// attachment;filename="sample.html"

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

When used in combination with Content-Disposition: attachment, it is used as the default filename for an eventual 'Save As" dialog presented to the user.

If the file name contains double-byte characters, use filename *.

String encodedFilename = URLEncoder.encode("sample.html", "UTF-8");
response.setHeader("Content-Disposition","attachment;filename*=\"UTF-8''" + encodedFilename + "\"");

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

The parameters "filename" and "filename*" differ only in that "filename*" uses the encoding defined in RFC 5987. When both "filename" and "filename*" are present in a single header field value, "filename*" is preferred over "filename" when both are present and understood.

Please note that half-width whitespace characters are converted to the plus sign "+". The code below will have the file name ʻa + b.html`.

String encodedFilename = URLEncoder.encode("a b.html", "UTF-8");
response.setHeader("Content-Disposition","attachment;filename*=\"UTF-8''" + encodedFilename + "\"");

This is a Java URL Encoder specification. https://docs.oracle.com/javase/jp/8/docs/api/java/net/URLEncoder.html

The whitespace character "" is converted to the plus sign "+".

If you replace the "+" with % 20, a whitespace character will appear in the file name. By the way, URLEncode has dialects depending on the language, so I will not go into it. .. .. https://www.glamenv-septzen.net/view/1170

Characters that cannot be used in the file name are converted to underscores. The code below will have the file name _________.html.

// ¥ / : * ? " < > |File name including
String encodedFilename = URLEncoder.encode("\\/:*\"<>|.html", "UTF-8");
response.setHeader("Content-Disposition","attachment;filename*=\"UTF-8''" + encodedFilename + "\"");

Both filename andfilename *

If you write both filename andfilename *as shown below, filename will be ignored if filename * is valid. If you consider browsers that do not support filename * (is there such a browser in 2017?), It seems good to write them together.

String encodedFilename = URLEncoder.encode("sample.html", "UTF-8");
response.setHeader("Content-Disposition","attachment;" + 
  "filename=\"sample.html\"" + 
  "filename*=\"UTF-8''" + encodedFilename + "\"");

Therefore, when both "filename" and "filename*" are present in a single header field value, recipients SHOULD pick "filename*" and ignore "filename".

Double quotes for filaname *

In the RFC 6266 example, filename has double quotes, butfilename *does not.

Content-Disposition: attachment;
                     filename="EURO rates";
                     filename*=utf-8''%e2%82%ac%20rates

If you put double quotes in filename * (filename * =" utf-8''sample.html "), the download result of each browser is as follows.

Other than Firefox, filename * was ignored and the filename was "download".

Download files under Apache

Enable mod_headers and specify the Content-disposition header. The following code will download all xml files under Apache.

LoadModule headers_module modules/mod_headers.so

<FilesMatch "\.(xml)$">
    Header set Content-Disposition attachment
</FilesMatch>

[Reference site] http://qiita.com/kompiro/items/ac60721bc43625a057dc

If you access http://sample.co.jp/sample.xml, it will be downloaded with the file name" sample.xml ". Notice that the file name is included in the URL. If the file name contains characters that have a special meaning as the URL, it will not be downloaded correctly. File names containing the following characters were not downloaded correctly. (Check with Firefox. It is unknown whether this is all the characters that cannot be used in the file name)

 # %

Download as HTML a element

If the download attribute is specified in the a element, the value specified in the download attribute will be downloaded as the file name. You can also use double-byte characters, single-byte spaces, and #, which has a special meaning as a URL. However, IE is not supported ...

<a href="sample.png " download="Test a b#%.png ">Download</a>

https://developer.mozilla.org/ja/docs/Web/HTML/Element/a

This attribute tells the browser to download instead of navigating to the URL, prompting the user to save it as a local file. If you specify a value for the attribute, it will be interpreted as the default filename for the save prompt (users can rename it if desired). There is no limit to the values that can be used, but / and \ convert to underscores. Many file systems have restrictions on the characters that can be used in filenames, and the browser may adjust the filenames.

<a href="sample.png " download="Test a b#%.png ">Download</a>

If you specify \ /: *?" <> | In the download attribute, all are converted to underscores (confirmed with Firefox). The code below will have the file name _________.html.

<a href="sample.png " download="&#x5c;/:*?&quot;&lt;&gt;|.png ">Download</a>

Precautions when downloading files under Tomcat

Prior to Tomcat 7 (?), The default for ʻURIEncoding is ʻISO-8859-1. This character code is a Latin alphabet character set and cannot represent Japanese.

https://tomcat.apache.org/tomcat-7.0-doc/config/http.html#Common_Attributes

This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.

Therefore, if you want to download a file containing Japanese, you need to set the character code to UTF-8.

server.xml


<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8" /><!--← Addendum-->

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"
URIEncoding="UTF-8"  /><!--← Addendum-->

In Tomcat8, the default is UTF-8, so you do not need to specify it.

https://tomcat.apache.org/tomcat-8.0-doc/config/http.html#Common_Attributes

This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, UTF-8 will be used unless the org.apache.catalina.STRICT_SERVLET_COMPLIANCE system property is set to true in which case ISO-8859-1 will be used.

[Reference site] http://qiita.com/kazuki43zoo/items/a365d194f5c4df28912f

Recommended Posts

How to download a file (Servlet, HTML, Apache, Tomcat)
How to download the old version of Apache Tomcat
Create a Java Servlet and JSP WAR file to deploy to Apache Tomcat 9 in Gradle
How to achieve file download with Feign
How to jump from Eclipse Java to a SQL file
How to convert a file to a byte array in Java
How to leave a comment
How to use Apache POI
How to insert a video
How to create a method
How to correctly check the local HTML file in the browser
How to request a CSV file as JSON with jMeter
[Ruby] How to split each GraphQL query into a file
How to deploy a simple Java Servlet app on Heroku
How to register as a customer with Square using Tomcat
How to use scope (JSP & Servlet)
How to create a jar file or war file using the jar command
SCP transfer War file to Tomcat
How to add columns to a table
How to make a jar file with no dependencies in Maven
How to make a Java container
How to sign a Minecraft MOD
How to make a JDBC driver
How to convert erb file to haml
How to load a Spring upload file and view its contents
[Java] How to create a folder
How to read a file and treat it as standard input
How to write a ternary operator
[Swift] How to send a notification
How to make a splash screen
How to make a Jenkins plugin
How to make a Maven project
[Beginner] How to delete NO FILE
How to open a script file from Ubuntu with VS code
[chown] How to change the owner of a file or directory
How to make a Java array
How to change from HTML to Haml
[IntelliJ IDEA] How to automatically add final when saving a Java file
How to run a GIF file from the Linux command line (Ubuntu)
How to find out the Java version of a compiled class file
How to start a Docker container with a volume mounted in a batch file
How to execute a contract using web3j
How to sort a List using Comparator
How to make a Java calendar Summary
A memorandum on how to use Eclipse
How to redo a deployment on Heroku
[Java] How to use the File class
How to delete the wrong migration file
[Basic] How to write a Dockerfile Self-learning ②
How to insert a video in Rails
How to delete the migration file NO FILE
How to add a new hash / array
How to add jar file in ScalaIDE
[Introduction to Java] How to write a Java program
How to make a Discord bot (Java)
Java: How to send values from Servlet to Servlet
How to print a Java Word document
[Servlet / Ajax] How to resolve NoClassDefFoundError [Eclipse]
[Swift5] How to create a splash screen
[rails] How to create a partial template
[Introduction to JSP + Servlet] A little animation ♬