The two common ways developers can serve static files are by saving them in a database and using a file server.
Saving files in a database is considered a bad practice as it affects the performance of your application. On the other hand, the best way to serve files is by using a file server such as Cloudinary.
In this tutorial, you will learn how to upload and serve static files in Spring Boot using Cloudinry. This will be a full fledge application covering both the back end and the front end.
Prerequisites
- Knowledge of Java programming language.
- Cloudinary account – Create a free account that provides you with 3 users and 25 monthly credits. The free account has a number of features that you can play with including uploading and transforming images.
- Java development kit(JDK)8 and above.
- IntelliJ community edition – development environment for the Java programming language.
Project setup
To create a new project, go to Spring initialzr and select Maven in the Project section, and also select Java in the Language section.
On the Spring Boot section, select 3.0 as the version, and on the Project Metadata section, enter the options as shown below.
- Group – com.javawhizz
- Artifact – fileServer
- Package name – com.javawhizz.fileServer
- Packaging – Jar
- Java – 17
To add dependencies, press the ADD button and add the dependencies Spring Web, Lombok, and Thymeleaf. Your project should have the following structure.

To download the project, press the GENERATE button and a ZIP folder of the project will be downloaded on your computer. Unzip the project and import it into IntelliJ.
The following dependency adds Cloudinary API to your project. Copy and paste it into the pom.xml file.
<dependency> <groupId>com.cloudinary</groupId> <artifactId>cloudinary-http44</artifactId> <version>1.32.2</version> </dependency>
Configure Cloudinary
To create a package to hold your configuration class, create a package named config under the package src/main/java/com/javawhizz/fileServer.
Create a file named CloudinaryConfig.java under the config package and copy and paste the following code into the file.
package com.javawhizz.fileServer.config; import com.cloudinary.Cloudinary; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; @Configuration public class CloudinaryConfig { private final String CLOUD_NAME = "YOUR_CLOUD_NAME"; private final String API_KEY = "YOUR_API_KEY"; private final String API_SECRET = "YOUR_API_SECRET"; @Bean public Cloudinary cloudinary(){ Map<String, String> config = new HashMap<>(); config.put("cloud_name",CLOUD_NAME); config.put("api_key",API_KEY); config.put("api_secret",API_SECRET); return new Cloudinary(config); } }
In this file, you have configured your Cloudinary
account by defining a bean and specifying the cloud name, API key, and API secret.
Enter the fields cloud_name
, api_key
, and api_secret
as specified when creating the account.
The bean definition will return a single instance every time you make a call to upload a file.
Create a File upload service
To create a package to hold the project service, create a package named service under the package src/main/java/com/javawhizz.
Create a file named FileUpload.java and copy and paste the following code into the file.
package com.javawhizz.fileServer.service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; public interface FileUpload { String uploadFile(MultipartFile multipartFile) throws IOException; }
In this file, you have created an interface that defines the method to upload your file. Since you want the method to return the file URL to be displayed on a web page, you make the method accept the parameter MultipartFile
and return a String
.
When uploading files, it is common to get input output exceptions such as file not found and due to this reason add an IOException
signature to the method.
In the next section, you will see how the method is implemented to upload the file and return the URL.
Implement the File upload service
Create a file named FileUploadImpl.java under the service package and copy and paste the following code into the file.
package com.javawhizz.fileServer.service; import com.cloudinary.Cloudinary; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.Map; import java.util.UUID; @Service @RequiredArgsConstructor public class FileUploadImpl implements FileUpload{ private final Cloudinary cloudinary; @Override public String uploadFile(MultipartFile multipartFile) throws IOException { return cloudinary.uploader() .upload(multipartFile.getBytes(), Map.of("public_id", UUID.randomUUID().toString())) .get("url") .toString(); } }
To upload a file, inject the Cloudinary
that you configured and call the uploader()
method inside the uploadFile()
method.
Call the upload()
method on the uploader()
method and pass the arguments multipartFile.getBytes()
and Map.of("public_id", UUID.randomUUID.toString())
.
The first argument sets the contents of the file and the second argument sets a random unique name for the file.
Once the file has been saved to the cloud, you will get a Map
response and calling the get()
method on the Map and passing the argument url
returns the URL of the file.
Call the toString()
method on the get()
method to get a string representation of the Object
returned.
Create a File upload controller
To create a package to hold the file upload controller, create a package named controller under the package src/main/java/com/javawhizz.
Create a file named FileUploadController.java under the controller package and copy and paste the following code into the file.
package com.javawhizz.fileServer.controller; import com.javawhizz.fileServer.service.FileUpload; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @Controller @RequiredArgsConstructor public class FileUploadController { private final FileUpload fileUpload; @RequestMapping("/") public String home(){ return "home"; } @PostMapping("/upload") public String uploadFile(@RequestParam("image")MultipartFile multipartFile, Model model) throws IOException { String imageURL = fileUpload.uploadFile(multipartFile); model.addAttribute("imageURL",imageURL); return "gallery"; } }
In this file, you have created a controller that will help you to load the form to submit a file and the page to display the file.
The first method home()
is the default access point to the application and it returns a web page named home.html that contains the form. You will create this form later.
The second method uploadFile()
creates the file on the cloud and returns a web page named gallery.html.
To create the file on the cloud, inject the FileUpload
service into the class and call the uploadFile()
method. Pass Multipartfile
as the argument of the method and create a variable to hold the string returned.
Add the string returned to the Model
using the addAttribute()
method for Thymeleaf to display the image once it is created.
Create a form to upload the file
Create a file named home.html under the folder src/main/resources/templates and copy and paste the following code into the file.
<!DOCTYPE html> <html lang="en" xmlns:th="https://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="#" th:action="@{/upload}" method="post" enctype="multipart/form-data"> <input type="file" name="image" placeholder="upload file"> <input type="submit" value="Submit"> </form> </body> </html>
In this file, you have created a form that makes a post request to /upload to create a file with the name image on Cloudinary.
Create a page to display the file
Create a file named gallery.html under folder src/main/resources/templates and copy and paste the following code into the file.
<!DOCTYPE html> <html lang="en" xmlns:th="https://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body style="background-color: cadetblue"> <div style="text-align: center"> <img style="height: 200px; width: 300px" th:src="@{${imageURL}}" alt="test image"> </div> </body> </html>
In this HTML file, you have created a page that displays the image created on Cloudinary using Thymeleaf.
Ensure the name of the image added to the model is the same as the name displayed by Thymeleaf. For example, in this case, the name imageURL
is the same for both the model and Thymeleaf.
Run and test the application
To run the application press the run icon located on the top right side of IntelliJ as shown below.

If your application starts without any errors, go to localhost:8080. Your browser should display the following page.

If your image is created without any errors, it should be displayed on the browser.

Conclusion
In this tutorial, you have learned how to upload and serve images in Spring Boot using Cloudinary. To achieve this you have implemented both the back end and the front end with the use of Thymeleaf to display an image.
You have uploaded one image in this tutorial. However, you can play around with the project to upload multiple files. You can also add transformations to the images with the help of the transformation features provided by Cloudinary.
If you are a visual learner, this article is also available on Youtube. The code for this tutorial is available on GitHub to help you compare your code.
Happy coding!
0 Comments