Open In App

Spring MVC – Implementing File Uploads and Downloads

Last Updated : 06 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

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.

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:

Project Folder Structure

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:

HTML
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/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:

User Interface

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:

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:

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.

Application Running


Step 6: Output

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

http://localhost:8080/

Output:

Output
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.



Next Article
Article Tags :

Similar Reads