How to Create a Spring Boot REST API for Multipart File Uploads: A Comprehensive Guide

Saumil Patel
18 min readApr 29, 2023

--

Developing your own API can be both exciting and useful. Think you have created an API that is capable of uploading any file type, including PDFs, PNGs, JPGs, TXTs, and more. In this article, we will see how to create a Spring Boot REST API that can upload and retrieve files to the database and file system.

We will be using an H2 in-memory database instead of a production database, but it’s easy to connect to any database by simply adding the necessary dependency and data source properties.

In general, our simple project will be designed around two important things:

  • Service layer to hold file storage logic.
  • One single controller for handling upload requests/responses.

Without further ado, let’s start!

1) Setting up Spring Boot Project

We will use the Spring Initializr for setting up the version of SpringBoot and Java. You can provide the Group ID and Artifact ID of your choice (In my case, the group id is ‘com.springapi’ & artifact id is ‘uploading’). Some of the dependencies would be selected beforehand as shown in the image.

Note: Select the Java version which you have installed on your system (In my case, the version is 17).

Let’s talk about the dependencies that we are going to use:

H2 database is an embedded, open-source, in-memory relational database management system written in Java. It can be used as a client/server application and is commonly used for unit testing. The database stores data in memory and does not persist the data on disk.

The Lombok dependency to get the auto-generated Getters, Setters, All Args Constructor, and No Args Constructor.

The Spring Web is a module of the Spring Framework that supports web applications. It includes features for handling web requests, managing sessions, and communicating with web services.

The SpringBoot DevTools module is to provide additional development time. Applications that use DevTools automatically restart whenever files on the classpath change. This can be a useful feature when working in an IDE, as it gives a very fast feedback loop for code changes.

Spring Data JPA uses all features defined by the JPA specification, including entity, association mappings, and query capabilities. Spring Data JPA adds features such as the no-code implementation of the repository pattern and the creation of database queries from the method name.

Now, click on the GENERATE button. The file will be downloaded to the path you have specified. Unzip the file and import it into your preferred IDE, such as Eclipse, IntelliJ, NetBeans, or BlueJ. In our case, we used IntelliJ for this purpose. Once you have imported the file, it may take some time for the necessary dependencies to download.

Now, head over to the pom.xml file in the project where you will see all the dependencies that you selected earlier.

As you can see below, I have added two more dependencies for JUnit tests.

Copy the below code and paste it to the pom.xml file to add both dependencies.

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>

Also, don’t forget to mention the version in the property tag. As you can see below, we have added the versions of the above dependencies as <junit.jupiter.version>5.4.0</junit.jupiter.version>

2) Uploading one or multiple files to a database

2.1) REST API

REST API is a service that transfers requests and responses between two software systems, in a REST architecture.

The REST architecture builds web services accessible through URLs using four request verbs: POST, GET, PUT, and DELETE. So, you could say a REST API is software that allows you to create, read, update, and delete resources via URLs.

A sample API to understand HTTP method type, parameters, and return type:

@PostMapping("/single/upload")
public ResponseEntity<String> fileUploading(@RequestParam("file") MultipartFile file) {
// Code to save the file to a database or disk
return ResponseEntity.ok("Successfully uploaded the file");
}

To upload files using HTTP in Spring Boot, the most commonly used method is POST. Here, the file is sent in the body of the HTTP request, along with any other associated information such as the filename or description. The response object returned by the method usually indicates whether the upload was successful or not, along with any additional metadata related to the file.

In the above sample API, @PostMapping annotation indicates that this method should handle HTTP POST requests to the “/single/upload” endpoint. The @RequestParam annotation specifies that the file parameter should be taken from the HTTP request’s multipart/form-data body. The return type is a ResponseEntity<String> object that contains a success message indicating that the file was uploaded successfully.

HTTP Status Codes

An HTTP status code is a server response to a browser’s request. When you visit a website, your browser sends a request to the site’s server, and the server then responds to the browser’s request with a three-digit code: the HTTP status code.

The most common Status Codes used are:

a) HTTP Status Code 200 — OK

b) HTTP Status Code 301 — Permanent Redirect

c) HTTP Status Code 302 — Temporary Redirect

d) HTTP Status Code 404 — Not Found

e) HTTP Status Code 500 — Internal Server Error

Now that you have gained a thorough understanding of REST APIs and the associated terminology it is time to start working on the project.

2.2) Configuring the H2 database in the project

Now for the configuration of the database:

  1. Go to the resources folder
  2. Open the application.properties file and type the following code:
spring.datasource.url = jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true

This configuration sets up an H2 database with default login credentials and enables the H2 console for easy management and querying of the database.

  • spring.datasource.url specifies the URL for the H2 database connection. In this case, it is an in-memory database with the name “testdb”.
  • spring.datasource.driverClassName specifies the class name for the JDBC driver that connects to the H2 database.
  • spring.datasource.username and spring.datasource.password specifies the login credentials for the H2 database. The default username is “sa” and the password is “password”.
  • spring.h2.console.enabled is a boolean property that enables or disables the H2 console, which provides a web-based interface for accessing the database.

2.3) Configuring the Maximum and Minimum File Size

Open the application.properties file and add the following lines:

spring.servlet.multipart.file-size-threshold=2KB
spring.servlet.multipart.max-file-size=200MB
spring.servlet.multipart.max-request-size=215MB

2.4) Creating a Model Class

Inside the project, under the com.springapi.uploading package makes a new package name model.

Then in the package model make a class name Product. In the class declare the following variables:

package com.springapi.uploading.model;
import jakarta.persistence.*;
import org.hibernate.annotations.GenericGenerator;
import jakarta.persistence.Entity;
import lombok.*;

@Builder
@Entity
@Data@AllArgsConstructor
@NoArgsConstructor
@Table(name = "product")
public class Product {

@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
private String fileName;
private String fileType;
@Lob
private byte[] data;

public Product(String fileName, String fileType, byte[] data) {
this.fileName = fileName;
this.fileType = fileType;
this.data = data;
}
}

In the above code, all the annotations used are explained below:

  • @Builder is an annotation that is used to generate a builder pattern for the class, which provides a convenient way to create instances of the class with less code.
  • @Entity is an annotation that indicates that this class is a JPA entity, which means it will be mapped to a database table.
  • @Data is an annotation that generates boilerplate code for the class, including getters, setters, and toString methods.
  • @AllArgsConstructor generates a constructor that takes all of the fields as arguments, while @NoArgsConstructor generates a constructor with no arguments.
  • @Table(name = “product”) is an annotation that specifies the name of the database table that this entity will be mapped to.
  • @Id is an annotation that specifies that the “id” field is the primary key for the table.

2.5) Creating a Repository Class

Inside the project, under the com.springapi.uploading package makes a new package name ProductRepo.

Then in the package repo make an interface name Repository which will further extend the JpaRepository.

package com.springapi.uploading.repo;

import com.springapi.uploading.model.Product;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepo extends JpaRepository<Product, Long> {
}

JPA repositories are created by extending the JpaRepository library consisting of the implementation of different functions, methods, and other related dependent data types to enable persistence in web or desktop applications designed using JAVA. Once the interface is created then functions like “save()”, “count()”, “info()”, “findAll()”, “sort()” and others are used to accomplish the data query or required data manipulation.

Inside the angular brackets, you have to provide the model name and data type of the primary key, in this case, it is of Long data type.

2.6) Creating Service Interface and ServiceImpl Class with Error Handling

Inside the project, under the com.springapi.uploading package makes a new package name service.

Then in the package service make an interface name ProductService and declare the following methods:

package com.springapi.uploading.service;
import java.util.List;
import com.springapi.uploading.model.Product;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
public interface ProductService {

Product saveAttachment(MultipartFile file) throws Exception;
void saveFiles(MultipartFile[] files) throws Exception;
List<Product> getAllFiles();
}

In the above code we have defined three methods:

  1. saveAttachment: This method takes a MultipartFile object as an argument and returns a Product object after saving the file as an attachment.
  2. saveFiles: This method takes an array of MultipartFile objects as an argument and saves all the files. It can throw an exception.
  3. getAllFiles: This method returns a list of all File objects that are uploaded.

To complete the implementation of the ProductService interface, we need to create a new class called ProductServiceImpl in the same package. It will implement all the methods defined in the interface and add the necessary business logic to perform the required operations. We will handle the exception in the same process.

In the class, we will make an object of the ProductRepository class to access all the methods of JpaRepository.

package com.springapi.uploading.service;

import com.springapi.uploading.model.Product;
import com.springapi.uploading.repo.ProductRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.List;
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductRepo fileRepository;
@Override
public Product saveAttachment(MultipartFile file) throws Exception {

String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {

if(fileName.contains("..")) {
throw new Exception("Filename contains invalid path sequence " + fileName);
}
if (file.getBytes().length > (1024 * 1024)) {
throw new Exception("File size exceeds maximum limit");
}
Product attachment = new Product(fileName, file.getContentType(), file.getBytes());
return fileRepository.save(attachment);
} catch (MaxUploadSizeExceededException e) {
throw new MaxUploadSizeExceededException(file.getSize());
} catch (Exception e) {
throw new Exception("Could not save File: " + fileName);
}
}
@Override
public void saveFiles(MultipartFile[] files) {

Arrays.asList(files).forEach(file -> {
try {
saveAttachment(file);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
@Override
public List<Product> getAllFiles() {
return fileRepository.findAll();
}
}

Spring Service annotation is used with classes that provide some business functionalities. Spring context will autodetect these classes when annotation-based configuration and classpath scanning is used.

Here Autowired annotation of the spring framework enables you to inject the object dependency implicitly. It internally uses a setter or constructor injection.

Note: Autowiring can’t be used to inject primitive and string values. It works with reference only.

Working of saveAttachment method:

The method takes a MultipartFile object as an argument, which represents the file to be saved and then extracts the file name using the clean path method of the StringUtils class. After that, it checks if the file name contains any invalid path sequences by checking if it contains “..” which would lead to throwing an exception with an error message.

Next, it checks if the file size exceeds the maximum limit, and the method throws an exception with an error message. Otherwise, if they are valid, the method creates a new Product object with the fileName, contentType, and bytes obtained from the MultipartFile object.

Finally, the method calls the save method of the Repository to save the product and returns it. If there is an error in the process, the method catches the exception and throws a new exception with a suitable error message.

Working of saveFiles method:

The method takes an array of MultipartFile objects as input. It iterates over each file in the array using a forEach loop. For each file, it calls the saveAttachment method and passes the current file as an argument.

If an exception occurs during the process of saving the file, the code will throw a new RuntimeException with the exception object as its argument.

Working of getAllFiles method:

This method returns a List of Product objects. It uses the Repository object to call the findAll method and retrieve all the Product objects saved in the database. Finally, it returns a List of Product objects.

2.7) Creating Response Class

package com.springapi.uploading.service;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ResponseClass {
private String fileName;
private String downloadUrl;
private String fileType;
private long fileSize;
}

This class can be used to create a response object after a file is uploaded. This object is returned to the client as a JSON object with the details of the uploaded file, including its name, download URL, type, and size.

2.8) Creating Controller Class

Inside the project, under the com.springapi.uploading package makes a new package name controller.

Then in the package controller make an interface name ProductController and declare the following REST APIs:

package com.springapi.uploading.controller;
import com.springapi.uploading.model.Product;
import com.springapi.uploading.service.ProductService;
import com.springapi.uploading.service.ResponseClass;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/files")
public class ProductController {
@Autowired
private ProductService fileService;

// for uploading the SINGLE file to the database
@PostMapping("/single/base")
public ResponseClass uploadFile(@RequestParam("file") MultipartFile file) throws Exception {

Product attachment = null;
String downloadURl = "";
attachment = fileService.saveAttachment(file);
downloadURl = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(attachment.getId())
.toUriString();

return new ResponseClass(attachment.getFileName(),
downloadURl,
file.getContentType(),
file.getSize());
}

//for uploading the MULTIPLE files to the database
@PostMapping("/multiple/base")
public List<ResponseClass> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) throws Exception {
List<ResponseClass> responseList = new ArrayList<>();
for (MultipartFile file : files) {
Product attachment = fileService.saveAttachment(file);
String downloadUrl = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(attachment.getId())
.toUriString();
ResponseClass response = new ResponseClass(attachment.getFileName(),
downloadUrl,
file.getContentType(),
file.getSize());
responseList.add(response);
}
return responseList;
}
//for retrieving all the files uploaded
@GetMapping("/all")
public ResponseEntity<List<ResponseClass>> getAllFiles() {
List<Product> products = fileService.getAllFiles();
List<ResponseClass> responseClasses = products.stream().map(product -> {
String downloadURL = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(product.getId())
.toUriString();
return new ResponseClass(product.getFileName(),
downloadURL,
product.getFileType(),
product.getData().length);
}).collect(Collectors.toList());

return ResponseEntity.ok().body(responseClasses);
}
}

The RestController annotation in Spring is essentially just a combination of Controller and ResponseBody. This annotation was added during Spring 4.0 to remove the redundancy of declaring the ResponseBody annotation in your controller.

The code defines a REST API controller class called ProductController with three API endpoints that allow users to upload and retrieve files.

  • The first endpoint, “/api/files/single/base”, accepts a single file as input and saves it to the database using the saveAttachment method of the ProductService interface.

The download URL is generated using the ServletUriComponentsBuilder class to construct a URL that can be used to download the saved file. It returns a ResponseClass object containing information about the uploaded file, such as its name, download URL, content type, and size.

  • The second endpoint, “/api/files/multiple/base”, allows users to upload multiple files at once. It iterates over each file in the input array and saves them to the database using the saveAttachment method. It then generates a ResponseClass object for each file and returns a list of all objects.
  • The third endpoint, “/api/files/multiple/base”, retrieves all files uploaded so far using the getAllFiles method of the ProductService interface. It then generates a ResponseClass object for each file and returns a list of all objects.

3) Uploading one or multiple files to a File System

It is very simple. You just have to provide the path of the folder where you want to upload the files and that is it. If you follow the code and explanation, you’re good to go.

Go to the controller class and include these two REST APIs for uploading files to the File System.

//for uploading the SINGLE file to the File System
@PostMapping("/single/file")
public ResponseEntity<ResponseClass> handleFileUpload(@RequestParam("file") MultipartFile file) {
String fileName = file.getOriginalFilename();
try {
file.transferTo(new File("D:\\Folder\\" + fileName));
String downloadUrl = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(fileName)
.toUriString();
ResponseClass response = new ResponseClass(fileName,
downloadUrl,
file.getContentType(),
file.getSize());
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
//for uploading the MULTIPLE file to the File system
@PostMapping("/multiple/file")
public ResponseEntity<List<ResponseClass>> handleMultipleFilesUpload(@RequestParam("files") MultipartFile[] files) {
List<ResponseClass> responseList = new ArrayList<>();
for (MultipartFile file : files) {
String fileName = file.getOriginalFilename();
try {
file.transferTo(new File("D:\\Folder\\" + fileName));
String downloadUrl = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(fileName)
.toUriString();
ResponseClass response = new ResponseClass(fileName,
downloadUrl,
file.getContentType(),
file.getSize());
responseList.add(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
return ResponseEntity.ok(responseList);
}

The handleFileUpload method handles the upload of a single file. The @RequestParam annotation is applied to obtain the file as input. The file is then saved to a specified directory on the disk using the transferTo() method. After saving the file, the method creates a download URL and returns a custom response object containing file details like filename, downloadUrl, contentType, and size of the uploaded file.

The handleMultipleFilesUpload method is used to handle the upload of multiple files, where the @RequestParam annotation is applied to obtain the files as input. The files are then saved to a specified directory on the disk using the transferTo() method in a loop. After saving all files, the method creates a download URL for each file. It adds them to a list of custom response objects containing details of all uploaded files.

4)Testing the Rest APIs using PostMan

4.1) Testing the API to upload Single file to the database

Finally, run the application and then open Postman, then follow these steps to upload a single file to the database:

  1. Create a new request and set the request type to “POST” and enter the URL of the API endpoint.
  2. Go to the “Body” tab and select the “form-data” option.
  3. Add the required key-value pairs. Add a key called “file” and select any file from the local machine.
  4. Click on the “Send” button to send the request.
  5. You will receive a response in the form of a JSON object.

To check whether the file has been uploaded to the database or not, open any browser and type the URL given below in the URL bar and press Enter button:

http://localhost:8080/h2-console

After that put the username “sa” and password as “password” because the same configuration we have done in the application.properties file and click on connect button. Take the reference from the image given below:

You will redirect to the embedded database. Inside the database type, the query

Select * from product; then press the Run button to get the following result:

Our API is working fine for uploading a single file to the database since the data has been saved. Let us check other APIs too.

4.2) Testing the API to upload multiple files to the database

Follow the similar steps as we have done in uploading a single file. We just have to change the endpoint and replace the key-value pairs. Add a key called “files” select any number of files from the local machine and press the “SEND” button like in the image given below:

After this, check in the database whether these files have been uploaded or not, then run the same query. It will lead to a table showing all files have been saved.

4.3) Testing the API to upload a single file to the File System

Follow the same steps as uploading a single file. We just have to change the endpoint and replace the key-value pairs. Add a key called “file” and select any file from the local machine and press the “SEND” button like in the image below:

Now, open the specified folder in your local machine and you will be able to see your uploaded file.

4.4) Testing the API to upload multiple files to the File System.

Follow the same steps as uploading a single file. We just have to change the endpoint and replace the key-value pairs. Add a key called “files” and select any number of files from the local machine and press the “SEND” button like in the image below:

Now, open the specified folder in your local machine and you will be able to see your uploaded files.

4.5) Testing the API to display the files uploaded already

Follow the same steps as uploading a single file. We just have to change the endpoint and no need for Key-value pairs. Change the Request type to GET press the “SEND” button and you will get the list of all the files like in the image below:

5) Creating JUnit Tests

JUnit is a unit testing framework for Java. JUnit has been important in test-driven development and is one of a family of unit testing frameworks known as xUnit that originated with SUnit.

JUnit is linked as a JAR at compile-time; the framework resides under package junit.framework for JUnit 3.8 and earlier, and under package org.junit for JUnit 4 and later.

5.1) JTest for Single file Upload

Simply go to the test folder present in the project directory. Then open the UploadingApplicationTests.java class. In your case name, but after the class name Tests word is common.

package com.springapi.uploading;

import com.springapi.uploading.model.Product;
import com.springapi.uploading.repo.ProductRepo;
import com.springapi.uploading.service.ProductService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import java.util.List;

@SpringBootTest
class UploadingApplicationTests {
@Autowired
private ProductRepo productRepo;
@Autowired
private ProductService productService;
// @Test
// void contextLoads() {
// }
@Test
public void testSaveAttachment() throws Exception {
MockMultipartFile mockFile = new MockMultipartFile(
"file", "test.txt", "text/plain", "Hello, world!".getBytes());
Product product = productService.saveAttachment(mockFile);
assertNotNull(product.getId());
assertEquals("test.txt", product.getFileName());
assertEquals("text/plain", product.getFileType());
}
}

This JUnit test checks the saveAttachment() method in the ProductService interface. A mock MultipartFile object is created and passed to the method, which saves the file to the file system and returns a Product object. The test checks that the returned Product object has an ID, a file name, and a file type. These values match the mock file values. If any of these conditions fail, the test will fail.

5.2) JTest for Multiple file upload

Add a new method in the class to test if the API can handle multiple files uploading.

@Test
public void testSaveFiles() throws Exception {
MockMultipartFile mockFile1 = new MockMultipartFile(
"file", "test1.pdf", "text/plain", "Hello, world!".getBytes());
MockMultipartFile mockFile2 = new MockMultipartFile(
"file", "test2.txt", "text/plain", "Goodbye, world!".getBytes());
productService.saveFiles(new MockMultipartFile[]{mockFile1, mockFile2});
List<Product> products = productService.getAllFiles();
System.out.println("Saved files:");
for (Product product : products) {
System.out.println(product.getFileName());
}
assertEquals(2, products.size());
assertEquals("test1.pdf", products.get(0).getFileName());
assertEquals("test2.txt", products.get(1).getFileName());
}
@BeforeEach
public void setUp() {
productRepo.deleteAll();
}

This JUnit test checks the saveFiles method in the ProductService interface. It creates two mock files using the MockMultipartFile class and passes them to the saveFiles method. Then, it retrieves all the saved files from the database using the getAllFiles method. It checks that the correct files were created by comparing their names to the expected values. If the test passes, the output should show the names of the saved files, and the two assertions at the end should succeed.

@BeforeEach runs before each test method in a JUnit test class.

The setUp method deletes all records from a repository called ProductRepo, which is likely used to store Product objects in a database, before each test case. This ensures that the repository is empty before each test case is executed, providing a clean slate for testing.

5.3) JTest to check for an invalid file name

 @Test
public void testSaveAttachmentInvalidName() {
MockMultipartFile mockFile = new MockMultipartFile(
"file", "../test.txt", "text/plain", "Hello, world!".getBytes());
assertThrows(Exception.class, () -> productService.saveAttachment(mockFile));
}

This JUnit test method checks the saveAttachment() method of the ProductService class. It creates a MockMultipartFile object with an invalid file name and asserts that the method should throw an exception. This test verifies that the saveAttachment() method handles invalid file names properly.

5.4) JTest to check for the size of the file

@Test
public void testSaveAttachmentTooLarge() {
byte[] bytes = new byte[1024 * 1024 * 10];
MockMultipartFile mockFile = new MockMultipartFile(
"file", "test.txt", "text/plain", bytes);
assertThrows(Exception.class, () -> productService.saveAttachment(mockFile));
}

This JUnit test case checks whether the saveAttachment() method of the ProductService object causes an exception when the file size is too large. In this case, a byte array of size 10 MB is created and converted into a mock file. The assertThrows() method checks if the saveAttachment() method throws an exception when the mock file is passed as input. If an exception is thrown, the test case passes.

Finally, we will run the UploadingApplicationTests.java class and all the test cases would be passed in the JUnit window as shown in the image below:

7) Conclusion

That’s all my friend! In this article, we have learned how to implement a REST API for uploading files to both the file system and database using Spring Boot. We have also covered important topics such as configuring the maximum and minimum file size, validating file types and formats, handling multiple uploads, error handling, and testing.

By following the steps outlined in this article, anyone can build a robust and reliable file upload functionality for their applications using Spring Boot.

--

--