Spring MVC file download
In any web application, it is very much common that we need to download the file.
So Spring MVC provides a simple way for doing it.
We just need to follow below steps to achieve this
1) create a hyperlink in the view page to provide them a click to download the file
2) create the controller which can handle this click request and write a code to get the file from the server and return it
Lets see the project implementation
Project structure
Pom.xml with required dependencies
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>Spring</groupId>
- <artifactId>SpringMVCFileDownload</artifactId>
- <packaging>war</packaging>
- <version>0.0.1-SNAPSHOT</version>
- <name>File Download Maven Webapp</name>
- <url>http://maven.apache.org</url>
- <properties>
- <org.springframework.version>4.2.0.RELEASE</org.springframework.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.5</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>javax.servlet.jsp.jstl</groupId>
- <artifactId>javax.servlet.jsp.jstl-api</artifactId>
- <version>1.2.1</version>
- </dependency>
- <!-- Apache Commons FileUpload -->
- <dependency>
- <groupId>commons-fileupload</groupId>
- <artifactId>commons-fileupload</artifactId>
- <version>1.3.1</version>
- </dependency>
- <!-- Apache Commons IO -->
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.4</version>
- </dependency>
- <dependency>
- <groupId>taglibs</groupId>
- <artifactId>standard</artifactId>
- <version>1.1.2</version>
- </dependency>
- </dependencies>
- <build>
- <finalName>SpringMVCFileDownload</finalName>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.5.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Spring</groupId> <artifactId>SpringMVCFileDownload</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>File Download Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <org.springframework.version>4.2.0.RELEASE</org.springframework.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>1.2.1</version> </dependency> <!-- Apache Commons FileUpload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <!-- Apache Commons IO --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> </dependencies> <build> <finalName>SpringMVCFileDownload</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
web.xml
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1">
- <display-name>Spring MVC File Download</display-name>
- <!-- Spring MVC dispatcher servlet -->
- <servlet>
- <servlet-name>mvc-dispatcher</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/spring-mvc.xml,
- </param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>mvc-dispatcher</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- </web-app>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Spring MVC File Download</display-name> <!-- Spring MVC dispatcher servlet --> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-mvc.xml, </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
create the spring configuration file
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
- <context:component-scan base-package="com.kb.*" />
- <mvc:annotation-driven />
- <bean id="viewResolver"
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/WEB-INF/pages/" />
- <property name="suffix" value=".jsp" />
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="com.kb.*" /> <mvc:annotation-driven /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
create the FileDownloadController
- package com.kb.controllers;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import javax.servlet.ServletContext;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.context.ServletContextAware;
- import org.springframework.web.multipart.MultipartFile;
- import org.springframework.web.servlet.ModelAndView;
- @Controller
- public class FileDownloadController implements ServletContextAware {
- private ServletContext servletContext;
- private static final int BUFFER_SIZE = 4096;
- private String filePath = "/downloads/example.pdf";
- @RequestMapping(value = "/displayForm", method = RequestMethod.GET)
- public ModelAndView downloadFileFormDisplay() {
- return new ModelAndView("downloadFile");
- }
- //Handle the single file upload
- @RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
- public void doDownload(HttpServletRequest request,HttpServletResponse response) throws IOException {
- // get the absolute path of the application
- String appPath = servletContext.getRealPath("");
- System.out.println("appPath = " + appPath);
- // absolute path of the file
- String fullPath = appPath + filePath;
- File downloadFile = new File(fullPath);
- FileInputStream inputStream = new FileInputStream(downloadFile);
- // MIME type of the file
- String mimeType = servletContext.getMimeType(fullPath);
- if (mimeType == null) {
- // Set to binary type if MIME mapping not found
- mimeType = "application/octet-stream";
- }
- System.out.println("MIME type: " + mimeType);
- // set content attributes for the response object
- response.setContentType(mimeType);
- response.setContentLength((int) downloadFile.length());
- // set headers for the response object
- String headerKey = "Content-Disposition";
- String headerValue = String.format("attachment; filename=\"%s\"",
- downloadFile.getName());
- response.setHeader(headerKey, headerValue);
- // get output stream of the response
- OutputStream outStream = response.getOutputStream();
- byte[] buffer = new byte[BUFFER_SIZE];
- int bytesRead = -1;
- // write each byte of data read from the input stream into the output stream
- while ((bytesRead = inputStream.read(buffer)) != -1) {
- outStream.write(buffer, 0, bytesRead);
- }
- inputStream.close();
- outStream.close();
- }
- public void setServletContext(ServletContext servletContext) {
- this.servletContext=servletContext;
- }
- }
package com.kb.controllers; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.context.ServletContextAware; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; @Controller public class FileDownloadController implements ServletContextAware { private ServletContext servletContext; private static final int BUFFER_SIZE = 4096; private String filePath = "/downloads/example.pdf"; @RequestMapping(value = "/displayForm", method = RequestMethod.GET) public ModelAndView downloadFileFormDisplay() { return new ModelAndView("downloadFile"); } //Handle the single file upload @RequestMapping(value = "/downloadFile", method = RequestMethod.GET) public void doDownload(HttpServletRequest request,HttpServletResponse response) throws IOException { // get the absolute path of the application String appPath = servletContext.getRealPath(""); System.out.println("appPath = " + appPath); // absolute path of the file String fullPath = appPath + filePath; File downloadFile = new File(fullPath); FileInputStream inputStream = new FileInputStream(downloadFile); // MIME type of the file String mimeType = servletContext.getMimeType(fullPath); if (mimeType == null) { // Set to binary type if MIME mapping not found mimeType = "application/octet-stream"; } System.out.println("MIME type: " + mimeType); // set content attributes for the response object response.setContentType(mimeType); response.setContentLength((int) downloadFile.length()); // set headers for the response object String headerKey = "Content-Disposition"; String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName()); response.setHeader(headerKey, headerValue); // get output stream of the response OutputStream outStream = response.getOutputStream(); byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; // write each byte of data read from the input stream into the output stream while ((bytesRead = inputStream.read(buffer)) != -1) { outStream.write(buffer, 0, bytesRead); } inputStream.close(); outStream.close(); } public void setServletContext(ServletContext servletContext) { this.servletContext=servletContext; } }
In this controller, we are reading the file from the specified path(in our case it is inside our project downloads folder and it is example.pdf file) and then finally writing it to the response output stream.
We have used MIME type check to add default MIME type as binary if no MIME mapping is found
Create the view page downloadFile.jsp
- <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
- pageEncoding="ISO-8859-1"%>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
- <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Hello</title>
- </head>
- <body>
- <center>
- <h2><a href="${pageContext.request.contextPath}/downloadFile">Click here to download the file</a></h2>
- </center>
- </body>
- </html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Hello</title> </head> <body> <center> <h2><a href="${pageContext.request.contextPath}/downloadFile">Click here to download the file</a></h2> </center> </body> </html>
Deploy the application and access the below url
http://localhost:8080/SpringMVCFileDownload/displayForm
Click on the hyperlink and it will ask for the confirmation to download as below
Click on save
File will be downloaded in your system downlad folder by default.
Change the browser setting to download it into specific path if you want.
Hi,
what will be the approach to download/open a list of files in the browser one after another?
Nice one. Good for preparation.And beginners can understand what it is.
Thank you !!
Nice Article……
Thanks Rahul !!