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



Maven [Pom.xml]

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">
&nbsp;Delete&nbsp;</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

From the browser call the endpoint http://localhost:8080

All the best!

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Spring boot video streaming example-HTML5

Spring Boot + Mockito simple application with 100% code coverage

Spring Boot + OpenCSV Export Data to CSV Example

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Custom Exception Handling in Quarkus REST API

ReactJS, Spring Boot JWT Authentication Example

DataTable-Pagination example with Spring boot, jQuery and ajax

Spring Webflux File Download Example

Node JS mini projects with source code - free download