Spring MVC Download File Examples
In this tutorial we show you how to use Spring MVC to download a file. You can either download a file as an attachment or directly view the file inside the browser. To show the file directly in the browser, the browser needs to support the specified file type. We demonstrate the file download using multiple methods: via HttpServletResponse, via HttpEntity and via FileSystemResource. We also show you how to handle exceptions while downloading.
Spring MVC Download File
The DownloadController
below is used to download a file. There are three ways you can download a file via Spring MVC. Later in this example, we’ll take a look at them individually. Notice that when we get the file, we check if the file exists. If the file does not exist, we throw a FileNotFoundException
before we set any headers on the response. This is important, otherwise the exception handler will not properly resolve the exception.
package com.memorynotfound.controller;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
@Controller
@RequestMapping("/download")
public class DownloadController {
private static final String FILE_PATH = "/tmp/example.pdf";
private static final String APPLICATION_PDF = "application/pdf";
@RequestMapping(value = "/a", method = RequestMethod.GET, produces = APPLICATION_PDF)
public @ResponseBody void downloadA(HttpServletResponse response) throws IOException {
File file = getFile();
InputStream in = new FileInputStream(file);
response.setContentType(APPLICATION_PDF);
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
response.setHeader("Content-Length", String.valueOf(file.length()));
FileCopyUtils.copy(in, response.getOutputStream());
}
@RequestMapping(value = "/b", method = RequestMethod.GET, produces = APPLICATION_PDF)
public @ResponseBody HttpEntity<byte[]> downloadB() throws IOException {
File file = getFile();
byte[] document = FileCopyUtils.copyToByteArray(file);
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "pdf"));
header.set("Content-Disposition", "inline; filename=" + file.getName());
header.setContentLength(document.length);
return new HttpEntity<byte[]>(document, header);
}
@RequestMapping(value = "/c", method = RequestMethod.GET, produces = APPLICATION_PDF)
public @ResponseBody Resource downloadC(HttpServletResponse response) throws FileNotFoundException {
File file = getFile();
response.setContentType(APPLICATION_PDF);
response.setHeader("Content-Disposition", "inline; filename=" + file.getName());
response.setHeader("Content-Length", String.valueOf(file.length()));
return new FileSystemResource(file);
}
private File getFile() throws FileNotFoundException {
File file = new File(FILE_PATH);
if (!file.exists()){
throw new FileNotFoundException("file with path: " + FILE_PATH + " was not found.");
}
return file;
}
}
Download File via HttpServletResponse
We can use the HttpServletResponse
to write a file directly to the ServletOutputStream
using the FileCopyUtils
. Note that the return type of this method is void. First, – in order that the browser understands which file is sent over the wire – we need to set the appropriate headers like: Content-Type, Content-Disposition and Content-Length. The Content-Disposition header instructs the browser which filename is used to download the file and whether the file needs to be downloaded as an attachment or displayed in the browser. Using the attachment like we did here, will directly download the file as an attachment.
@RequestMapping(value = "/a", method = RequestMethod.GET, produces = APPLICATION_PDF)
public @ResponseBody void downloadA(HttpServletResponse response) throws IOException {
File file = getFile();
InputStream in = new FileInputStream(file);
response.setContentType(APPLICATION_PDF);
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
response.setHeader("Content-Length", String.valueOf(file.length()));
FileCopyUtils.copy(in, response.getOutputStream());
}
Download File via HttpEntity
We can also use the HttpEntity
. This time we return a HttpEntity<byte[]>
. We set the same headers like before using the HttpHeaders
, but instead of attachment we use inline to instruct the browser to display the file directly in the browser – if the file type is supported.
@RequestMapping(value = "/b", method = RequestMethod.GET, produces = APPLICATION_PDF)
public @ResponseBody HttpEntity<byte[]> downloadB() throws IOException {
File file = getFile();
byte[] document = FileCopyUtils.copyToByteArray(file);
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "pdf"));
header.set("Content-Disposition", "inline; filename=" + file.getName());
header.setContentLength(document.length);
return new HttpEntity<byte[]>(document, header);
}
Download File via Resource
Instead of managing the InputStream
we can also let Spring MVC handle the streams using the FileSystemResource
. There are many implementations of the Resource
class, couple of examples:
- The
ClassPathResource
searches for a given file on the classpath, this could either be dynamically loaded on the classpath or resides as a file inside your project. - The
UrlResource
supports file resolution as aURL
resource. - …
@RequestMapping(value = "/c", method = RequestMethod.GET, produces = APPLICATION_PDF)
public @ResponseBody Resource downloadC(HttpServletResponse response) throws FileNotFoundException {
File file = getFile();
response.setContentType(APPLICATION_PDF);
response.setHeader("Content-Disposition", "inline; filename=" + file.getName());
response.setHeader("Content-Length", String.valueOf(file.length()));
return new FileSystemResource(file);
}
File Download Exception handling
Remember that after we retrieve the file, we inspect if the file exists. If the file does not exist, we throw a FileNotFoundException
. This is not the only exception the code could throw. A IOException
could also occur when the file is written to the OutputStream
. We handle both exceptions using these exception handlers below. By annotating the class with @ControllerAdvice
this class will be registered by spring as a global exception handler. The @ExceptionHandler
annotation, in conjunction with the expected exception will handle those exceptions. Inside these handlers we re-trown the exception using the correct status code and the given error message.
package com.memorynotfound.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = FileNotFoundException.class)
public void handle(FileNotFoundException ex, HttpServletResponse response) throws IOException {
System.out.println("handling file not found exception");
response.sendError(404, ex.getMessage());
}
@ExceptionHandler(value = IOException.class)
public void handle(IOException ex, HttpServletResponse response) throws IOException {
System.out.println("handling io exception");
response.sendError(500, ex.getMessage());
}
}
File Download View
We demonstrate this Spring MVC Download example using the following view. These links on the page will trigger each method individually and according to the Content-Disposition attribute, they will download the file as an attachment or directly display the file in the browser.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring MVC Download File Example</title>
</head>
<body>
<h1>Spring MVC Download File Example</h1>
<a href="<c:url value='/download/a'/>">Download file via servlet response.</a><br/>
<a href="<c:url value='/download/b'/>">Download file via http entity.</a><br/>
<a href="<c:url value='/download/c'/>">Download file via file system resource.</a><br/>
</body>
</html>
Demo
Downloaded the file as an attachment.
Directly display the file in the browser.
Hi,
thanks for this tutorial. I wonder where the function getFile() is defined. It is clear that you useit in order to get the file from somewhere in the system, but I just want to be sure I don’t miss anything. Regards,
Victor
How can I download the file from any Front End MVC (like Angular JS) by receiving byte array as response?