Spring MVC Download File Controller Example

In Spring MVC application, to download a resource such as a file to the browser, you need to do the following in your controller.

  1. Use the void return type for your request-handling method and add HttpServletResponse as an argument to the method.
  2. Set the response’s content type to the file’s content type. If you do not know what the content type is or want the browser to always display the Save As dialog, set it to APPLICATION/OCTET-STREAM (NOT case sensitive).
  3. Add an HTTP response header named Content-Disposition and give it the value attachment; filename=fileName, where fileName is the default file name that should appear in the File Download dialog box.

1. Sping MVC File Download Controller

Let’s look at an example implementation for file download controller.

@Controller
@RequestMapping("/download")
public class FileDownloadController 
{
	@RequestMapping("/pdf/{fileName:.+}")
	public void downloadPDFResource( HttpServletRequest request, 
									 HttpServletResponse response, 
									 @PathVariable("fileName") String fileName) 
	{
		//If user is not authorized - he should be thrown out from here itself
		
		//Authorized user will download the file
		String dataDirectory = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/");
		Path file = Paths.get(dataDirectory, fileName);
		if (Files.exists(file)) 
		{
			response.setContentType("application/pdf");
			response.addHeader("Content-Disposition", "attachment; filename="+fileName);
			try 
			{
				Files.copy(file, response.getOutputStream());
				response.getOutputStream().flush();
			} 
			catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}
}
If you want to enable downloads for only authorized users then check the user’s logged in status first in the method, and then allow download otherwise redirect him to login screen.

Now if you hit the application URL : http://localhost:8080/springmvcexample/download/pdf/sample.pdf, you will be able to get the Save As dialog box in your browser like below:

File download window
File download window

The file is placed inside folder “/WEB-INF/downloads/pdf”. You are free to change the path – make sure you change the controller code as well.

File download project structure
File download project structure

2. Prevent Cross-Referencing of File Downloads

Many times, other websites may cross reference your files in their websites as direct links. You may not want to allow it. To disallow all download requests, coming from other domains, you can check if the referer header contains your domain name.

Our modified FileDownloadController will send files to the browser, only if the referer header is not null. This will prevent the images from being downloaded directly by typing their URLs in the browser or request coming from other domains.

@Controller
@RequestMapping("/download")
public class FileDownloadController 
{
	@RequestMapping("/pdf/{fileName:.+}")
	public void downloadPDFResource( HttpServletRequest request, 
									 HttpServletResponse response, 
									 @PathVariable("fileName") String fileName,
									 @RequestHeader String referer) 
	{
		//Check the renderer
		if(referer != null && !referer.isEmpty()) {
			//do nothing
			//or send error
		}
		//If user is not authorized - he should be thrown out from here itself
		
		//Authorized user will download the file
		String dataDirectory = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/");
		Path file = Paths.get(dataDirectory, fileName);
		if (Files.exists(file)) 
		{
			response.setContentType("application/pdf");
			response.addHeader("Content-Disposition", "attachment; filename="+fileName);
			try 
			{
				Files.copy(file, response.getOutputStream());
				response.getOutputStream().flush();
			} 
			catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}
}

Now if you try to hit the URL from browser directly, you will get this error:

java.lang.IllegalStateException: Missing header 'referer' of type [java.lang.String]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.raiseMissingHeaderException(HandlerMethodInvoker.java:797)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestHeader(HandlerMethodInvoker.java:566)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:355)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:172)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)

Drop me your questions in comments section.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

12 thoughts on “Spring MVC Download File Controller Example”

  1. sir, how to prevent pdf file being downloaded in certain field? from {filename = } that has different id from other documents.
    thankyou

    Reply
  2. how to display files like images, pdf, zip from the local folder in JSP using spring MVC
    using while loop to display all files in folder

    Reply
  3. can please tell me that how to download a file in another folder like

    my applications in D:/Project/

    my file saved in Another Directory like E:/Upload/Docs/Naresh.doc how to download
    can u please tell me

    Reply
  4. Hi i have to do same but i need to send request header with download url for user authentication. so m not getting how ill add request header with it?

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.