Spring Boot Web Application Export and Download Text File

Tags: Spring Boot Download File Java IO Java NIO

Introduction

In this tutorial we learn how to create a new text file and provide the user the web interface to download the text file in a Spring Boot web application. We will learn how to download a text file in Spring Boot with 5 different approaches to implement the feature.

Create New Spring Boot Web Project

From Spring Tool Suite IDE select menu File > New > Spring Starter Project.

On the New Spring Starter Project popup input new project spring-boot-download-text-file information as following screenshot.

Spring Boot Web Application Export and Download Text File - Create New Project

On the New Spring Starter Project Dependencies popup choose dependencies:

  • Template Engines: Thymeleaf
  • Web: Spring Web

Spring Boot Web Application Export and Download Text File - Create New Project

You can also creating new Spring Boot project using Spring initializr online tool at start.spring.io

Implement Text File Export Service

Next, we implement the service class to export a String into a text file.

Create a new Java package named dev.simplesolution.service and add FileExporter interface.

package dev.simplesolution.service;

import java.nio.file.Path;

public interface FileExporter {
	
	public Path export(String fileContent, String fileName);
	
}

Create a new Java package named dev.simplesolution.service.impl and implement TextFileExporter service class.

package dev.simplesolution.service.impl;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import dev.simplesolution.service.FileExporter;

@Service
public class TextFileExporter implements FileExporter {

	private static final String EXPORT_DIRECTORY = "D:\\SimpleSolution";
	
	private Logger logger = LoggerFactory.getLogger(TextFileExporter.class);
	
	@Override
	public Path export(String fileContent, String fileName) {
		Path filePath = Paths.get(EXPORT_DIRECTORY, fileName);
		try {
			Path exportedFilePath = Files.write(filePath, fileContent.getBytes(), StandardOpenOption.CREATE);
			return exportedFilePath;
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}	
		return null;
	}
}

Implement File Downloading Controller

Create a new Java package named dev.simplesolution.controller and create DownloadController class.

Firstly, inject the FileExporter to the controller and implement a method in order to show the index page.

@Controller
public class DownloadController {
	
	@Autowired
	private FileExporter fileExporter;
	
	@RequestMapping("/")
	public String index() {
		return "index";
	}
}

Solution 1 - Implement download file with InputStreamResource

@RequestMapping("/download1")
public ResponseEntity<InputStreamResource> downloadTextFileExample1() throws FileNotFoundException {
	String fileName = "example1.txt";
	String fileContent = "Simple Solution \nDownload Example 1";
	
	// Create text file
	Path exportedPath = fileExporter.export(fileContent, fileName);
		
	// Download file with InputStreamResource
	File exportedFile = exportedPath.toFile();
	FileInputStream fileInputStream = new FileInputStream(exportedFile);
	InputStreamResource inputStreamResource = new InputStreamResource(fileInputStream);
	
	return ResponseEntity.ok()
			.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
			.contentType(MediaType.TEXT_PLAIN)
			.contentLength(exportedFile.length())
			.body(inputStreamResource);
}

Solution 2 - Implement download file with ByteArrayResource

@RequestMapping("/download2")
public ResponseEntity<ByteArrayResource> downloadTextFileExample2() throws IOException {
	String fileName = "example2.txt";
	String fileContent = "Simple Solution \nDownload Example 2";
		
	// Create text file
	Path exportedPath = fileExporter.export(fileContent, fileName);
		
	// Download file with ByteArrayResource
	byte[] exportedFileData = Files.readAllBytes(exportedPath);
	ByteArrayResource byteArrayResource = new ByteArrayResource(exportedFileData);
		
	return ResponseEntity.ok()
			.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
			.contentType(MediaType.TEXT_PLAIN)
			.contentLength(exportedFileData.length)
			.body(byteArrayResource);	
}

Solution 3 - Implement download file with Resource

@RequestMapping("/download3")
public ResponseEntity<Resource> downloadTextFileExample3() throws IOException {
	String fileName = "example3.txt";
	String fileContent = "Simple Solution \nDownload Example 3";
		
	// Create text file
	Path exportedPath = fileExporter.export(fileContent, fileName);
		
	// Download file with Resource
	URI exportedFileUri = exportedPath.toUri();
	Resource resource = new UrlResource(exportedFileUri);
		
	return ResponseEntity.ok()
			.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
			.contentType(MediaType.TEXT_PLAIN)
			.contentLength(resource.contentLength())
			.body(resource);
}

Solution 4 - Implement download file with byte array

@RequestMapping("/download4")
public ResponseEntity<byte[]> downloadTextFileExample4() throws IOException {
	String fileName = "example4.txt";
	String fileContent = "Simple Solution \nDownload Example 4";
		
	// Create text file
	Path exportedPath = fileExporter.export(fileContent, fileName);
		
	// Download file with byte[]
	byte[] expotedFileData = Files.readAllBytes(exportedPath);
		
	return ResponseEntity.ok()
			.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
			.contentType(MediaType.TEXT_PLAIN)
			.contentLength(expotedFileData.length)
			.body(expotedFileData);
}

Solution 5 - Implement download file with HttpServletResponse

@RequestMapping("/download5")
public void downloadTextFileExample5(HttpServletResponse response) throws IOException {
	String fileName = "example5.txt";
	String fileContent = "Simple Solution \nDownload Example 5";
		
	// Create text file
	Path exportedPath = fileExporter.export(fileContent, fileName);
		
	// Download file with HttpServletResponse
	response.setContentType(MediaType.TEXT_PLAIN_VALUE);
	response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
	response.setContentLength((int)exportedPath.toFile().length());
		
	// Copy file content to response output stream
	Files.copy(exportedPath, response.getOutputStream());		
	response.getOutputStream().flush();
}

The final DownloadController class as follows.

package dev.simplesolution.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import dev.simplesolution.service.FileExporter;

@Controller
public class DownloadController {
	
	@Autowired
	private FileExporter fileExporter;
	
	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping("/download1")
	public ResponseEntity<InputStreamResource> downloadTextFileExample1() throws FileNotFoundException {
		String fileName = "example1.txt";
		String fileContent = "Simple Solution \nDownload Example 1";
		
		// Create text file
		Path exportedPath = fileExporter.export(fileContent, fileName);
		
		// Download file with InputStreamResource
		File exportedFile = exportedPath.toFile();
		FileInputStream fileInputStream = new FileInputStream(exportedFile);
		InputStreamResource inputStreamResource = new InputStreamResource(fileInputStream);
		
		return ResponseEntity.ok()
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
				.contentType(MediaType.TEXT_PLAIN)
				.contentLength(exportedFile.length())
				.body(inputStreamResource);
	}
	
	@RequestMapping("/download2")
	public ResponseEntity<ByteArrayResource> downloadTextFileExample2() throws IOException {
		String fileName = "example2.txt";
		String fileContent = "Simple Solution \nDownload Example 2";
		
		// Create text file
		Path exportedPath = fileExporter.export(fileContent, fileName);
		
		// Download file with ByteArrayResource
		byte[] exportedFileData = Files.readAllBytes(exportedPath);
		ByteArrayResource byteArrayResource = new ByteArrayResource(exportedFileData);
		
		return ResponseEntity.ok()
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
				.contentType(MediaType.TEXT_PLAIN)
				.contentLength(exportedFileData.length)
				.body(byteArrayResource);
	}
	
	@RequestMapping("/download3")
	public ResponseEntity<Resource> downloadTextFileExample3() throws IOException {
		String fileName = "example3.txt";
		String fileContent = "Simple Solution \nDownload Example 3";
		
		// Create text file
		Path exportedPath = fileExporter.export(fileContent, fileName);
		
		// Download file with Resource
		URI exportedFileUri = exportedPath.toUri();
		Resource resource = new UrlResource(exportedFileUri);
		
		return ResponseEntity.ok()
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
				.contentType(MediaType.TEXT_PLAIN)
				.contentLength(resource.contentLength())
				.body(resource);
	}
	
	@RequestMapping("/download4")
	public ResponseEntity<byte[]> downloadTextFileExample4() throws IOException {
		String fileName = "example4.txt";
		String fileContent = "Simple Solution \nDownload Example 4";
		
		// Create text file
		Path exportedPath = fileExporter.export(fileContent, fileName);
		
		// Download file with byte[]
		byte[] expotedFileData = Files.readAllBytes(exportedPath);
		
		return ResponseEntity.ok()
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
				.contentType(MediaType.TEXT_PLAIN)
				.contentLength(expotedFileData.length)
				.body(expotedFileData);
	}
	
	@RequestMapping("/download5")
	public void downloadTextFileExample5(HttpServletResponse response) throws IOException {
		String fileName = "example5.txt";
		String fileContent = "Simple Solution \nDownload Example 5";
		
		// Create text file
		Path exportedPath = fileExporter.export(fileContent, fileName);
		
		// Download file with HttpServletResponse
		response.setContentType(MediaType.TEXT_PLAIN_VALUE);
		response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
		response.setContentLength((int)exportedPath.toFile().length());
		
		// Copy file content to response output stream
		Files.copy(exportedPath, response.getOutputStream());		
		response.getOutputStream().flush();
	}
}

Create a new view file at \src\main\resources\templates\index.html and implement HTML code as below to allow the user click on the button to download the text file that is generated at the server side. In this HTML we also use Bootstrap CSS library.

<!DOCTYPE html>
<html>
	<head>
		<title>Download Text Files</title>
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">
	</head>
	<body class="container">
		<br>
		<h3>Click buttons below to download the files</h3>
		<br>
		<a href="/download1" class="btn btn-primary">
			Download Text File Example 1
		</a>
		<br>
		<br>
		<a href="/download2" class="btn btn-secondary">
			Download Text File Example 2
		</a>
		<br>
		<br>
		<a href="/download3" class="btn btn-success">
			Download Text File Example 3
		</a>
		<br>
		<br>
		<a href="/download4" class="btn btn-danger">
			Download Text File Example 4
		</a>
		<br>
		<br>
		<a href="/download5" class="btn btn-info">
			Download Text File Example 5
		</a>
	</body>
</html>

Final Application

The final Spring Boot web application structure looks like the following screenshot.

Spring Boot Web Application Export and Download Text File - Application structure

Run the Spring Boot web application and visit http://localhost:8080/ on your browser to open the web user interface as following screenshot.

Download Files user interface

Then we can click on the button to download the text file.

Conclusion

In this tutorial we have learned different solutions to download a text file in a Spring Boot web application and how to export a text file in Java.

Download Source Code

The source code in this article can be found at: github.com/simplesolutiondev/spring-boot-download-text-file

or clone at:

git clone https://github.com/simplesolutiondev/spring-boot-download-text-file.git

or download at:

Download Source Code

Happy Coding 😊