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.
On the New Spring Starter Project Dependencies popup choose dependencies:
- Template Engines: Thymeleaf
- Web: Spring Web
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 HTML View to represent the link for Downloading
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.
Run the Spring Boot web application and visit http://localhost:8080/ on your browser to open the web user interface as following screenshot.
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:
Happy Coding 😊