Introduction

File download example using Spring REST Controller will show you how to download a file from any client (browser or any client) and Spring REST service is used as a server side technology for downloading the file. The file may be any type, i.e., such as excel, text, word, pdf etc. Here we will create Spring Boot application as it reduces our most of the efforts in project configurations.

We have seen how to download a file using REST web service using Jersey API in my other tutorial but here we will see how to download a file using Spring REST Controller.

You may also like to read my previous tutorial on file upload using Spring REST Controller.

For various reasons, such as, reporting or any other purpose you may need to download file and in our today’s application we are using mostly REST services to make the application loosely coupled, it is sometimes required to download the file using REST service.

Recommended reading: Junit Testing of File Upload and Download in Spring REST Controllers

Let’s move on to file download example using Spring REST Controller…

Prerequisites

Knowledge of Spring REST API
Eclipse 2019-12, At least Java 8, Gradle 6.1.1, maven 3.6.3, Spring Boot 2.2.5, MySQL 8.0.17

Set up project

As a prerequisite we have to first setup the project environment so that we would be able to write the required code for downloading file into server and save the file anywhere on a physical location in your system. Create below build.gradle script to add the required project dependencies. We have also specified the JDK version we will be using for our application. File download example using Spring REST Controller does not many dependencies and you need to add only spring boot started web for downloading a file.

buildscript {
	ext {
		springBootVersion = '2.2.5.RELEASE'
	}
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

plugins {
    id 'java-library'
    id 'org.springframework.boot' version "${springBootVersion}"
}

sourceCompatibility = 12
targetCompatibility = 12

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}")
    implementation('mysql:mysql-connector-java:8.0.17')
	//required only if jdk 9 or higher version is used
    runtimeOnly('javax.xml.bind:jaxb-api:2.4.0-b180830.0359')
}

If you are creating maven based project then you can use below pom.xml file:

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>spring-rest-file-download</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.5.RELEASE</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
		
		<!--required only if jdk 9 or higher version is used-->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.4.0-b180830.0359</version>
		</dependency>
	</dependencies>

    <build>
        <plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>at least 8</source>
					<target>at least 8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

application.properties

We are creating below application.properties file under classpath directory src/main/resources to configure the MySQL database settings. We do not need to create any datasource explicitly as we are using the standard naming conventions for database configurations and Spring Boot will automatically create one for us.

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/roytuts
spring.datasource.username=root
spring.datasource.password=root

Entity Class

Create below entity class that maps to database table. Our entity class has only three fields employee id, employee first name and employee last name. We are creating entity class because we want to create a file from our database record and finally download the file using Spring REST service. Here we will build a JSON file from database employee table and download that JSON file. You can build any type of file, such as excel file, csv file etc. to fulfil your project’s requirement.

package com.roytuts.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employee")
public class Employee implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@Column(name = "id")
	private Integer empId;

	@Column(name = "first_name")
	private String empFirstName;

	@Column(name = "last_name")
	private String empLastName;

	//getters and setters

}

Spring Data JPA Repository

Here in the file download example using Spring REST Controller, we are using Spring Data JPA in order to query the database and fetch data from database table. So create below Spring Data JPA Repository which provides most of our built-in methods to query database for fetching data.

package com.roytuts.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.roytuts.entity.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, Integer> {

}

Spring Service

Create below service class which will fetch data from Spring Data JPA Repository and send to Spring REST Controller that will generate the file for download. We fetch all employees from the database using the below service layer code. We annotate the service layer class using @Service. We create service layer class to process our business logic to avoid any tight coupling between the layers.

package com.roytuts.service;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.roytuts.entity.Employee;
import com.roytuts.repository.EmployeeRepository;

@Service
public class EmployeeService {

	@Resource
	private EmployeeRepository employeeRepository;

	public List<Employee> getEmployees() {
		return employeeRepository.findAll();
	}

}

Spring REST Controller

This is where we write code for file download example using Spring REST Controller. The below Spring REST Controller class to receive the downloaded file from client.

We have the http method GET request and the file can be downloaded from browser or any REST client or UI.

We use the data type as array of byte stream in the response to download the file. File may be downloaded from a selected location using the server side code or you may generated a report file from database and download the report file using the Spring REST Controller.

Notice how we attach the file in the http header response so that file will be forced to download and give a pop-up for saving it. You must specify few things, such as, content length, content type, attachment with file name in order to download the file forcefully.

package com.roytuts.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.roytuts.entity.Employee;
import com.roytuts.service.EmployeeService;

@RestController
public class FileDownloadRestController {

	@Autowired
	private EmployeeService employeeService;

	@GetMapping("/download")
	public ResponseEntity<byte[]> downloadErrorData() throws Exception {
		List<Employee> employees = employeeService.getEmployees();
		ObjectMapper objectMapper = new ObjectMapper();
		String json = objectMapper.writeValueAsString(employees);
		byte[] isr = json.getBytes();
		String fileName = "employees.json";
		HttpHeaders respHeaders = new HttpHeaders();
		respHeaders.setContentLength(isr.length);
		respHeaders.setContentType(new MediaType("text", "json"));
		respHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
		respHeaders.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
		return new ResponseEntity<byte[]>(isr, respHeaders, HttpStatus.OK);
	}

}

Creating Spring Boot Main Class

Now major coding part is done and it’s time to deploy the application into embedded tomcat server. Create below Spring Boot main class to deploy the application into Tomcat server.

package com.roytuts.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EntityScan(basePackages = "com.roytuts.entity")
@SpringBootApplication(scanBasePackages = "com.roytuts")
@EnableJpaRepositories(basePackages = "com.roytuts.repository")
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

MySQL Table

We will create employee table under roytuts database into MySQL server.

CREATE TABLE IF NOT EXISTS `employee` (
  `id` int(11) NOT NULL DEFAULT '0',
  `first_name` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
  `last_name` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `employee` (`id`, `first_name`, `last_name`) VALUES
	(1003349, 'Liton', 'Sarkar'),
	(1003350, 'Debabrata', 'Poddar'),
	(1003351, 'Abhisekh', 'Paul'),
	(1003352, 'Sumit', 'Ghosh'),
	(1003353, 'Manoj', 'Kumar'),
	(1003354, 'Sreeja', 'Chowdhury');

Testing the Application

Now it’s time to test the application for file download example using Spring REST Controller. You may also like to read my previous tutorial on file upload using Spring REST Controller.

When you hit the URL http://localhost:8080/download from browser or REST client then you would be able to receive the below JSON records in a file assuming your database employee table has the similar records.

[
	{"empId":"1003349","empFirstName":"Liton","empLastName":"Sarkar"},
	{"empId":"1003350","empFirstName":"Debabrata","empLastName":"Poddar"},
	{"empId":"1003351","empFirstName":"Abhisekh","empLastName":"Paul"},
	{"empId":"1003352","empFirstName":"Sumit","empLastName":"Ghosh"},
	{"empId":"1003353","empFirstName":"Manoj","empLastName":"Kumar"},
	{"empId":"1003354","empFirstName":"Sreeja","empLastName":"Chowdhury"}
]

Recommended reading: Junit Testing of File Upload and Download in Spring REST Controllers

Source Code

download source code

That’s all. Thanks for reading.

Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *