Spring MVC 4 - File download example



Spring MVC 4 - File download example

Technologies used:   Java SE 1.8 | Spring 4.3.9.RELEASE | Maven 3.3.9 | Apache Tomcat 7.0.47 | Eclipse Neon.3

In this post, I will show you how to develop a Spring MVC application to download files such as images, zip, pdf etc. from web server to local machine.

There are several approaches for downloading a file in Spring MVC application such as.

Using HttpServletRespone - You can use the HttpServletResponse to write a file directly to the ServletOutputStream.

Using ResponseEntity<InputStreamResource> - You can return a file as InputStreamResource, wrapped in the ResponseEntity, from controller’s handler method.

Using ResponseEntity<ByteArrayResource> - You can also return a file as ByteArrayResource wrapped in the ResponseEntity.

Let’s see a complete example…

 

Project structure

Review the following web project structure build using Maven.

Spring MVC 4 - File download example | BORAJI.COM

Related - How to create a web project using maven build tool in eclipse IDE.

 

Jar dependencies

Open pom.xml file of your maven project and add the following dependencies in it.

<dependencies>
  <!-- Spring MVC Dependency -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.9.RELEASE</version>
  </dependency>

  <!-- JSTL Dependency -->
  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>javax.servlet.jsp.jstl-api</artifactId>
    <version>1.2.1</version>
  </dependency>
  <dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
  </dependency>

  <!-- Servlet Dependency -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>

  <!-- JSP Dependency -->
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.1</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

 

Controller class

Create a controller class to handle the file download request as follows.

You need to set Content-Type, Content-Disposition and Content-Length headers before writing a file to the ServletOutputStream or returning a file as resource from a handler method.

FileDownloadController.java

package com.boraji.tutorial.spring.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.servlet.http.HttpServletResponse;

import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author imssbora
 */
@Controller
public class FileDownloadController {

   private static final String FILE_PATH = "D:/e-Books/jsp_tutorial.pdf";

   @GetMapping("/")
   public String fileUploadForm(Model model) {
      return "fileDownloadView";
   }

   // Using ResponseEntity<InputStreamResource>
   @GetMapping("/download1")
   public ResponseEntity<InputStreamResource> downloadFile1() throws IOException {

      File file = new File(FILE_PATH);
      InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

      return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION,
                  "attachment;filename=" + file.getName())
            .contentType(MediaType.APPLICATION_PDF).contentLength(file.length())
            .body(resource);
   }

   // Using ResponseEntity<ByteArrayResource>
   @GetMapping("/download2")
   public ResponseEntity<ByteArrayResource> downloadFile2() throws IOException {

      Path path = Paths.get(FILE_PATH);
      byte[] data = Files.readAllBytes(path);
      ByteArrayResource resource = new ByteArrayResource(data);

      return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION,
                  "attachment;filename=" + path.getFileName().toString())
            .contentType(MediaType.APPLICATION_PDF).contentLength(data.length)
            .body(resource);
   }

   // Using HttpServletResponse
   @GetMapping("/download3")
   public void downloadFile3(HttpServletResponse resonse) throws IOException {
      File file = new File(FILE_PATH);

      resonse.setContentType("application/pdf");
      resonse.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
      BufferedInputStream inStrem = new BufferedInputStream(new FileInputStream(file));
      BufferedOutputStream outStream = new BufferedOutputStream(resonse.getOutputStream());
      
      byte[] buffer = new byte[1024];
      int bytesRead = 0;
      while ((bytesRead = inStrem.read(buffer)) != -1) {
        outStream.write(buffer, 0, bytesRead);
      }
      outStream.flush();
      inStrem.close();
   }
}

ResponseEntity represent the HTTP response entity that contains body, header and status code. It can be used in RestTemplate and @Controller method.

 

JSP View

Create a fileDownloadView.jsp file under src\main\webapp\WEB-INF\views folder, which contains the download links.

fileDownloadView.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!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>BORAJI.COM</title>
</head>
<body>
  <h2>Spring MVC - File Download Example</h2>
  <hr>
  <ul>
    <li><a href="download1">Download File 1</a></li>
    <li><a href="download2">Download File 2</a></li>
    <li><a href="download3">Download File 3</a></li>
  </ul>
</body>
</html>

 

Spring configuration

Create a web @Configuration class annotated with @EnableWebMvc and @ComponentScan as follows. 

WebConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.Bean;
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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * @author imssbora
 */

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {

   @Bean
   public InternalResourceViewResolver resolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setViewClass(JstlView.class);
      resolver.setPrefix("/WEB-INF/views/");
      resolver.setSuffix(".jsp");
      return resolver;
   }
}

 

Servlet container initialization

Create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer class as follows.

MyWebAppInitializer.java

package com.boraji.tutorial.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * @author imssbora
 */
public class MyWebAppInitializer
      extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] {};
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

The AbstractAnnotationConfigDispatcherServletInitializer class, implements the WebApplicationInitializer, is implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically.

 

Build + Deploy + Run application

Use the following maven commands to build, deploy and run embedded Tomcat server.

mvn clean install  (This command triggers war packaging)

mvn tomcat7:run (This command run embedded tomcat and deploy war file automatically)

You can refer this link to learn how to run the above commands in Eclipse IDE.


Type the following URLs in browser's address bar to open the file download page.

http://localhost:8080/

Spring MVC 4 - File download example | BORAJI.COM

Click on Download File link to save file on local machine.

Spring MVC 4 - File download example | BORAJI.COM