This post shows you how to implement File Download using Spring MVC 4. We will see file download for file internal to application as well external file from file system. Let’s get going.
- Spring Boot+AngularJS+Spring Data+Hibernate+MySQL CRUD App
- Spring Boot REST API Tutorial
- Spring Boot WAR deployment example
- Spring Boot Introduction + Hello World Example
- Secure Spring REST API using OAuth2
- AngularJS+Spring Security using Basic Authentication
- Spring 4 Caching Annotations Tutorial
- Secure Spring REST API using Basic Authentication
- Spring 4 Cache Tutorial with EhCache
- Spring 4 MVC+JPA2+Hibernate Many-to-many Example
- Spring 4 Email Template Library Example
- Spring 4 Email With Attachment Tutorial
- Spring 4 Email Integration Tutorial
- Spring MVC 4+JMS+ActiveMQ Integration Example
- Spring 4+JMS+ActiveMQ @JmsLister @EnableJms Example
- Spring 4+JMS+ActiveMQ Integration Example
- Spring MVC 4+Spring Security 4 + Hibernate Integration Example
- Spring MVC 4+AngularJS Example
- Spring MVC 4+AngularJS Server communication example : CRUD application using ngResource $resource service
- Spring MVC 4+AngularJS Routing with UI-Router Example
- Spring MVC 4+AngularJS Routing with ngRoute Example
- Spring MVC 4 File Upload Example using Commons fileupload
- Spring MVC4 FileUpload-Download Hibernate+MySQL Example
- Spring MVC 4 File Upload Example using Servlet 3 MultiPartConfigElement
Main highlights of the posts:
Downloading a file is quite simple and involves following steps.
- Create an InputStream to the file to be downloaded.
- Find
MIME type
of the content of downloaded file.
– can be of application/pdf, text/html,application/xml,image/png, ..others. -
Set
Content-Type
in response(HttpServletResponse) with MIME type found above.
response.setContentType(mimeType); -
Set
Content length
in response with MIME type found above.
response.setContentLength(file.getLength());//length in bytes -
Set Content-Disposition HEADER in response.
response.setHeader(“Content-Disposition”, “attachment; filename=” + fileName); //With ‘attachement’ File will be downloaded as is. May show a ‘Save as’ dialog based on browser setting.response.setHeader(“Content-Disposition”, “inline; filename=” + fileName);//With ‘inline’ browser will try to display content right into broswer for certain contents(imgages,PDF,text,..). For other content types, file will be download directly.
- Copy bytes from InputStream to OutputStream of response.
- Once copying done, close input & output stream.
Complete Example is discussed below.
Following technologies being used:
- Spring 4.2.0.RELEASE
- Bootstrap v3.3.2
- Maven 3
- JDK 1.7
- Tomcat 8.0.21
- Eclipse JUNO Service Release 2
Let’s begin.
Project Structure
Declare dependencies in pom.xml
<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>com.websystique.springmvc</groupId> <artifactId>Spring4MVCFileDownloadExample</artifactId> <packaging>war</packaging> <version>1.0.0</version> <name>Spring4MVCFileDownloadExample Maven Webapp</name> <properties> <springframework.version>4.2.0.RELEASE</springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warSourceDirectory>src/main/webapp</warSourceDirectory> <warName>Spring4MVCFileDownloadExample</warName> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </pluginManagement> <finalName>Spring4MVCFileDownloadExample</finalName> </build> </project>
Create Controller
package com.websystique.springmvc.controller; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLConnection; import java.nio.charset.Charset; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class FileDownloadController { private static final String INTERNAL_FILE="irregular-verbs-list.pdf"; private static final String EXTERNAL_FILE_PATH="C:/mytemp/SpringMVCHibernateManyToManyCRUDExample.zip"; @RequestMapping(value={"/","/welcome"}, method = RequestMethod.GET) public String getHomePage(ModelMap model) { return "welcome"; } /* * Download a file from * - inside project, located in resources folder. * - outside project, located in File system somewhere. */ @RequestMapping(value="/download/{type}", method = RequestMethod.GET) public void downloadFile(HttpServletResponse response, @PathVariable("type") String type) throws IOException { File file = null; if(type.equalsIgnoreCase("internal")){ ClassLoader classloader = Thread.currentThread().getContextClassLoader(); file = new File(classloader.getResource(INTERNAL_FILE).getFile()); }else{ file = new File(EXTERNAL_FILE_PATH); } if(!file.exists()){ String errorMessage = "Sorry. The file you are looking for does not exist"; System.out.println(errorMessage); OutputStream outputStream = response.getOutputStream(); outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8"))); outputStream.close(); return; } String mimeType= URLConnection.guessContentTypeFromName(file.getName()); if(mimeType==null){ System.out.println("mimetype is not detectable, will take default"); mimeType = "application/octet-stream"; } System.out.println("mimetype : "+mimeType); response.setContentType(mimeType); /* "Content-Disposition : inline" will show viewable types [like images/text/pdf/anything viewable by browser] right on browser while others(zip e.g) will be directly downloaded [may provide save as popup, based on your browser setting.]*/ response.setHeader("Content-Disposition", String.format("inline; filename=\"" + file.getName() +"\"")); /* "Content-Disposition : attachment" will be directly download, may provide save as popup, based on your browser setting*/ //response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName())); response.setContentLength((int)file.length()); InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); //Copy bytes from source to destination(outputstream in this example), closes both streams. FileCopyUtils.copy(inputStream, response.getOutputStream()); } }
This Controller involves two files. One file is internal to application (inside resources), and other file is located on file system external to application. Be sure to change external file path for your project. Only for demonstration purpose, we have included an extra path variable(internal/external) in path. We are using Spring FileCopyUtils
utility class to copy stream from source to destination.
Configuration
package com.websystique.springmvc.configuration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.websystique.springmvc") public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{ @Override public void configureViewResolvers(ViewResolverRegistry registry) { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); registry.viewResolver(viewResolver); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("/static/"); } }
Initialization
package com.websystique.springmvc.configuration; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { HelloWorldConfiguration.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
Add View
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring 4 MVC File Download Example</title> <link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link> <link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link> </head> <body> <div class="form-container"> <h1>Welcome to FileDownloader Example</h1> Click on below links to see FileDownload in action.<br/><br/> <a href="<c:url value='/download/internal' />">Download This File (located inside project)</a> <br/> <a href="<c:url value='/download/external' />">Download This File (located outside project, on file system)</a> </div> </body> </html>
Build, Deploy & Run Application
Now build the war (either by eclipse as was mentioned in previous tutorials) or via maven command line( mvn clean install). Deploy the war to a Servlet 3.0 container . Since here i am using Tomcat, i will simply put this war file into tomcat webapps folder and click on start.bat inside tomcat/bin directory.
Open browser and browse at http://localhost:8080/Spring4MVCFileDownloadExample
Clink on Second link. External file should be downloaded.
Clink on First link. Internal file [which is a PDF] should be displayed in browser, thanks to Content-Disposition: inline.With inline, if the content can be shown by browser, it will show it in browser.
Now change Content-Disposition from inline to attachment. Build & redeploy. Click on First link.You should see that pdf file is downloaded this time.
That’s it. Next post shows File upload-download a file into database using Spring MVC 4 , Hibernate and MySQL.
Download Source Code
References
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.