Categories: springmvc

Spring MVC 4 File Download Example

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.

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

View Comments

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

8 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

8 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

8 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

8 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago