Spring Boot, Thymeleaf - File Upload, Download & Delete - Example
Hello everyone, Hope you are doing well. In this post, will learn how to upload, download, and delete the file with Spring Boot and Thymeleaf. You could download the source code from our GitHub repository.
Backend Project Directory
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project.
<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.knf.dev.demo</groupId>
<artifactId>spring-thymeleaf-file-upload-download</artifactId>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<properties>
<java.version>17</java.version>
</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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
You can configure the file upload limits by using spring.servlet.multipart.max-file-size and spring.servlet.multipart.max-request-size in application.properties/yaml.
#search multipart
spring.http.multipart.max-file-size=2MB
spring.http.multipart.max-request-size=10MB
Create File Controller
package com.knf.dev.demo.controller;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
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;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class FileController {
// Save the uploaded file to this folder
private static String UPLOADED_FOLDER =
"/home/user/Desktop/files/";
@GetMapping("/")
public String index(Model model) {
List<String> list = new ArrayList<String>();
File files = new File(UPLOADED_FOLDER);
String[] fileList = ((File) files).list();
for (String name : fileList) {
list.add(name);
}
model.addAttribute("list", list);
return "upload";
}
@PostMapping("/upload")
public String singleFileUpload
(@RequestParam("file") MultipartFile file, Model model) {
if (file.isEmpty()) {
model.addAttribute("warning",
"Please select a file to upload");
return "upload";
}
try {
byte[] bytes = file.getBytes();
Path path = Paths.get(UPLOADED_FOLDER +
file.getOriginalFilename());
Files.write(path, bytes);
model.addAttribute("message",
"You successfully uploaded '"
+ file.getOriginalFilename() + "'");
} catch (IOException e) {
model.addAttribute("error", "Error");
return "upload";
}
List<String> list = new ArrayList<String>();
File files = new File(UPLOADED_FOLDER);
String[] fileList = ((File) files).list();
for (String name : fileList) {
list.add(name);
}
model.addAttribute("list", list);
return "upload";
}
@GetMapping(path = "/download/{name}")
public ResponseEntity<Resource> download
(@PathVariable("name") String name) throws IOException {
File file = new File(UPLOADED_FOLDER + name);
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = new ByteArrayResource
(Files.readAllBytes(path));
return ResponseEntity.ok().headers(this.headers(name))
.contentLength(file.length())
.contentType(MediaType.parseMediaType
("application/octet-stream")).body(resource);
}
@PostMapping(path = "/delete")
public String delete(@RequestParam("name") String name)
throws IOException {
try {
Files.deleteIfExists(Paths.get(UPLOADED_FOLDER + name));
}
catch (IOException e) {
return "redirect:/";
}
return "redirect:/";
}
private HttpHeaders headers(String name) {
HttpHeaders header = new HttpHeaders();
header.add(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=" + name);
header.add("Cache-Control", "no-cache, no-store,"
+ " must-revalidate");
header.add("Pragma", "no-cache");
header.add("Expires", "0");
return header;
}
}
Create upload.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.4.1/css/all.css">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script
src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js">
</script>
</head>
<body>
<h2 style="text-align: center;">Spring Boot + Thymeleaf file
upload & download</h2>
<div class="container my-5">
<form method="POST" action="/upload" enctype="multipart/form-data">
<div class="form-group row">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupFileAddon01">Upload</span>
</div>
<div class="custom-file">
<input name="file" type="file" class="custom-file-input"
id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
<label class="custom-file-label" for="inputGroupFile01">Choose
file</label>
</div>
</div>
</div>
<div class="form-group row">
<input class="btn btn-primary" type="submit" value="Submit" />
</div>
<div class="form-group row">
<div th:if="${warning}">
<div class="alert alert-warning" role="alert">
<h4 th:text="${warning}" />
</div>
</div>
<div th:if="${message}">
<div class="alert alert-success" role="alert">
<h4 th:text="${message}" />
</div>
</div>
<div th:if="${error}">
<div class="alert alert-danger" role="alert">
<h4 th:text="${error}" />
</div>
</div>
</div>
</form>
<table class="table table-striped table-responsive-md">
<thead>
<tr>
<th>File Name</th>
</tr>
</thead>
<tbody>
<tr th:each="list : ${list}">
<td th:text="${list}"></td>
<td><a
th:href="@{http://localhost:8080/download/{name}(name=${list})}">
<button type="button" class="btn btn-success btn-sm">Download</button>
</a></td>
<td>
<form method="POST" action="/delete">
<input name="name" type="hidden" th:value="${list}" />
<button type="submit" class="btn btn-danger btn-sm">
Delete </button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Spring Boot Main Driver
package com.knf.dev.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Download the complete source code - click here
Local Setup and Run the application
Step1: Download or clone the source code from GitHub to the local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application - mvn spring-boot:run
Step1: Download or clone the source code from GitHub to the local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application - mvn spring-boot:run