Spring MVC – Implementing File Uploads and Downloads
Spring MVC is a widely used framework for developing robust web applications in Java. It simplifies handling HTTP requests and responses, including file uploads and downloads. File uploads enable users to send files to the server, while file downloads allow users to retrieve files from the server. This article explains how to create a user interface for uploading and downloading files with related examples and outputs for you to take a look at.
Application Features
Below are the features provided in this application:
- Responsive Web Application: Utilizes the Bootstrap framework for a responsive design.
- Upload Files: Enables users to upload files to a designated storage location.
- Display Files: Shows uploaded files in a table format with filenames and download buttons.
- Download Files: Allows users to download files individually by clicking a download button.
- Basic Error Handling: Prevents uploading of empty files.
Prerequisites
To understand this article you have basic knowledge in the below listed topics.
- Spring Boot Framework
- Spring Annotation
- Spring MVC
- Java Programming
- HTML and CSS
- Bootstrap Framework
- Web Design and Development
- File Handling in Spring Boot
Implementing File Uploads and Downloads using Spring MVC
Here's a step-by-step guide to creating a Spring Boot application that handles file uploads and downloads with a responsive web application design.
Step 1: Spring Application Creation
Create a Spring Boot application using Spring Initializr with the required dependencies.
To know, how to create a Spring Boot project, read this article: How to Create a Spring Boot Project?
Dependencies:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
Project Folder Structure:
After successfully creating the project, the folder structure will look like the below image:

application.properties:
Open the application.properties, and add below properties.
spring.application.name=filestorage
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
Step 2: Create HTML File
Create an HTML file in the src/main/resources/templates
folder and integrate the Bootstrap framework:
index.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload and Download</title>
</head>
<style>
form {
max-width: 900px;
height: auto;
border: 2px solid green !important;
}
</style>
<body>
<div class="files bg-success">
<div class="container">
<h3 class="text text-light p-3 text-center">Files Upload and Download</h3>
</div>
</div>
<div class="formdata mt-5 d-flex justify-content-center">
<div class="container">
<div class="row justify-content-center">
<form action="/upload" method="post" enctype="multipart/form-data" class="form-control p-4">
<div class="mb-3">
<label for="file" class="p-1" style="font-weight: bolder;">
<i class="fa fa-file-text"></i> Select File
</label>
<input type="file" name="file" id="file" class="form-control mt-3" required>
<button type="submit" class="btn btn-success form-control mt-4 text-light"
style="font-weight: bolder;">
<i class="fa fa-cloud-upload"></i> Upload File
</button>
</div>
</form>
</div>
<div class="tabledata mt-5">
<div class="table-responsive">
<table class="table table-bordered">
<thead class="bg-success text-light table-bordered">
<tr>
<th>File</th>
<th>Download</th>
</tr>
</thead>
<tbody class="text text-center">
<tr th:each="file : ${files}">
<td th:text="${file}"></td>
<td>
<a th:href="@{'/download/' + ${file}}" class="btn btn-success" style="border-radius: 100%; height: 40px; width: 40px;">
<i class="fa fa-cloud-download"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
Output:

Step 3: Create Service File
Create a service class to handle file operations. We have created the service class by using @Service in the main package in the project folder. In this class we have created different methods.
- saveFile() : This method is used for save the uploaded file in the mentioned location.
- loadFile() : This method is used for load the all the files from the storage folder.
- getAllFiles() : This method is used for retrieve all files from the storage folder for displaying purpose.
FileService.java:
package com.app;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
@Service
public class FileService {
private final Path fileStorageLocation;
public FileService() {
this.fileStorageLocation = Paths.get("uploads").toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
/**
* Saves the uploaded file to the specified location.
* @param file MultipartFile to be saved
*/
public void saveFile(MultipartFile file) {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
throw new RuntimeException("Could not store file " + fileName + ". Please try again!", ex);
}
}
/**
* Loads a file as a Resource for downloading.
* @param fileName the name of the file to be loaded
* @return Resource representing the file
*/
public Resource loadFile(String fileName) {
try {
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return resource;
} else {
throw new RuntimeException("File not found " + fileName);
}
} catch (MalformedURLException ex) {
throw new RuntimeException("File not found " + fileName, ex);
}
}
/**
* Retrieves all file names from the storage location.
* @return List of file names
*/
public List<String> getAllFiles() {
try {
return Files.walk(this.fileStorageLocation, 1)
.filter(path -> !path.equals(this.fileStorageLocation))
.map(this.fileStorageLocation::relativize)
.map(Path::toString)
.collect(Collectors.toList());
} catch (IOException ex) {
throw new RuntimeException("Could not list the files!", ex);
}
}
}
Step 4: Create File Controller
Create a controller class to handle HTTP requests. We have created a controller class by using @Controller annotation.
- getIndex() : This is one of the method created. This method is used for displaying the index.html file with GET mapping.
- uploadFile() : This method is used for uploading the files which is the POST mapping.
- downloadFile() : This method is used for download the files from the storage folder which is GET mapping.
FileController.java:
package com.app;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
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 {
@Autowired
private FileService fileService;
/**
* Displays the index page with a list of uploaded files.
* @param model the model to pass data to the view
* @return the name of the HTML template to be rendered
*/
@GetMapping("/")
public String getIndex(Model model) {
List<String> fileNames = fileService.getAllFiles();
model.addAttribute("files", fileNames);
return "index";
}
/**
* Handles file upload requests.
* @param file the file to be uploaded
* @param model the model to pass data to the view
* @return the redirect URL to the index page
*/
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file, Model model) {
fileService.saveFile(file);
model.addAttribute("message", "File uploaded successfully!");
return "redirect:/";
}
/**
* Handles file download requests.
* @param fileName the name of the file to be downloaded
* @return the ResponseEntity containing the file resource
*/
@GetMapping("/download/{fileName:.+}")
public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {
Resource resource = fileService.loadFile(fileName);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
}
Step 5: Run the Application
Once Business logic is develop for uploading and downloading files from the storage location. Run this application as Spring Boot App. And by default this application runs on port number 8080.

Step 6: Output
Access the application at http://localhost:8080
in your web browser.
http://localhost:8080/
Output:

Output Video:
Below is the entire output video:
Conclusion
This article demonstrated how to implement file upload and download functionality in a Spring Boot application. By following the provided code examples, you can easily create a file management system that allows users to upload and download files, all within a responsive web application interface.