Document Upload in Java with Spring Boot

Introduction

In this article, we will demonstrate how to implement a dynamic document upload feature using Spring Boot in Java. The functionality allows users to upload multiple documents by dynamically adding or removing file input fields on a web page. The uploaded files are then processed and saved on the server, providing flexibility in handling user-generated content. This feature is essential for applications where users need to upload multiple files, such as document management systems, online forms, or any service requiring file submissions.

This document Upload part is essential in building any software or any web application where user engagement is there. We may need to upload the profile picture or file or may need to remove it whenever required, just like we do in WhatsApp, facebook, or any other web application. This functionality I have to work on currently when working on my project where I need to have a similar functionality for the end user.

Real Use Case

Consider an online job application portal where applicants need to upload various documents, such as resumes, cover letters, certifications, and portfolio files. The number of documents required may vary depending on the job position. Using the dynamic document upload feature, the portal allows applicants to upload multiple files with the flexibility to add or remove document input fields as needed. This approach improves user experience and simplifies file management on the server side.

Example Implementation in Java with Spring Boot

  1. Create the Model: Define a model to hold the uploaded file data.
    import org.springframework.web.multipart.MultipartFile;
    import java.util.ArrayList;
    import java.util.List;
    public class DocumentUploadModel {
        private List<MultipartFile> files = new ArrayList<>();
        // Getters and Setters
        public List<MultipartFile> getFiles() {
            return files;
        }
        public void setFiles(List<MultipartFile> files) {
            this.files = files;
        }
    }
    
  2. Create the Controller: Implement the controller to handle the form submissions and save the uploaded files.
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    @Controller
    public class DocumentController {
        // Define constants for the upload directory and allowed file types
        private static final String UPLOAD_DIR = "/path/to/upload/directory";
        private static final List<String> ALLOWED_FILE_TYPES = List.of("pdf", "doc", "docx");
        @GetMapping("/upload")
        public String uploadForm(Model model) {
            model.addAttribute("documentUploadModel", new DocumentUploadModel());
            return "uploadForm";
        }
        @PostMapping("/uploadDocuments")
        public String uploadDocuments(@ModelAttribute DocumentUploadModel documentUploadModel, Model model) {
            List<MultipartFile> files = documentUploadModel.getFiles();
            if (files != null && !files.isEmpty()) {
                for (MultipartFile file : files) {
                    if (!file.isEmpty()) {
                        String fileName = file.getOriginalFilename();
                        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
                        // Validate file type
                        if (!ALLOWED_FILE_TYPES.contains(fileType)) {
                            model.addAttribute("message", "Invalid file type: " + fileType);
                            return "uploadForm";
                        }
                        try {
                            File destFile = new File(UPLOAD_DIR + File.separator + fileName);
                            file.transferTo(destFile);
                        } catch (IOException e) {
                            model.addAttribute("message", "Failed to upload file: " + fileName);
                            return "uploadForm";
                        }
                    }
                }
                model.addAttribute("message", "Files successfully uploaded!");
                return "uploadSuccess";
            }
            model.addAttribute("message", "No files selected to upload.");
            return "uploadForm";
        }
    }
    
  3. Create the View: Implement a simple HTML form to dynamically add or remove file input fields. This is the temporary view, user can have it accessed when hosted to the proper hostname and port number.
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Dynamic Document Upload</title>
        <script>
            function addFileInput() {
                var fileInputsDiv = document.getElementById("fileInputs");
                var newInput = document.createElement("div");
                newInput.innerHTML = '<input type="file" name="files" />';
                fileInputsDiv.appendChild(newInput);
            }
        </script>
    </head>
    <body>
        <h2>Upload Documents</h2>
        <form action="#" th:action="@{/uploadDocuments}" method="post" enctype="multipart/form-data">
            <div id="fileInputs">
                <div><input type="file" name="files" /></div>
            </div>
            <button type="button" onclick="addFileInput()">Add Another Document</button>
            <br/><br/>
            <input type="submit" value="Upload" />
        </form>
        <p th:text="${message}"></p>
    </body>
    </html>
    
    
  4. Configure File Upload Directory: Set up the directory where files will be saved in the application.properties file. Here using the properties file but added the code with the YAML extension.
    upload.dir=/path/to/upload/directory
    

Running the Application

  • Start the Spring Boot application: When users visit /upload, they are presented with the form to upload documents.
  • Upload Files: Users can dynamically add file inputs and submit the form.
  • Files are Saved: The files are saved in the configured upload directory, and a success message is displayed.

This implementation provides a flexible and user-friendly way to handle multiple document uploads in a Java-based web application.

API Request and Response

Request

To hit the API for uploading documents, you can use a tool like Postman or cURL. For simplicity, here's how to use cURL to simulate a file upload request.

Response

Depending on the outcome of the upload process, you might receive one of the following responses.

  • Successful Upload
    Successful Upload
  • Error in Upload
    Error
  • Invalid File Type
    File type
  • Test Results with Postman
    Postman

Conclusion

Implementing a dynamic document upload feature in your Java Spring Boot application significantly enhances the user experience, especially in scenarios where the number of documents to be uploaded can vary. By allowing users to dynamically add or remove file input fields, you provide a more flexible and intuitive interface that adapts to their needs. This approach is particularly useful in applications such as job portals, online forms, and content management systems, where users need to submit multiple documents.

The code example provided demonstrates the core components needed to set up this functionality, including the model, controller, and view, as well as configuring the file upload directory. By following this guide, you can quickly integrate a robust and user-friendly document upload feature into your Java-based web applications.

As a next step, you might consider adding features like file validation (e.g., checking file types and sizes), progress bars to enhance user feedback during the upload process, or integrating with cloud storage services for scalable file management.

Advance Options

For further reading on advanced file upload features in Spring Boot, including validation, handling large files, and integration with external storage services, consider exploring the following resources.

  1. Spring Boot File Upload Guide
  2. Handling Large File Uploads in Spring Boot
  3. Integrating AWS S3 with Spring Boot for File Storage

I'll be writing more articles on the above-mentioned topics with detailed examples and demonstration links. Until then, stay tuned for some of the next articles on Java Real Use Cases.

By expanding on the basics covered in this article, we can build a comprehensive file upload system that meets the needs of any modern web application.