Developers building software with media features must store the media somewhere and, in most cases, transform and optimize it for the best experience possible. All the tasks involved they can perform with Cloudinary's end-to-end image- and video management solution.
However, while building a Spring Boot REST API a while ago, I found that integrating with Cloudinary was a struggle, for it took a lot of time combing through GitHub repositories and debugging errors. In addition, although the Cloudinary documentation is pretty good, it does not describe the workflow for Spring Boot, and I had to figure that out on my own.
This tutorial walks you through the process of programmatically uploading media to Cloudinary from a Spring Boot application, saving you the time and effort I had to put in to get my code to work. For a sample reference, see my Spring Boot API on GitHub.
Acquiring the Prerequisites
You must have the following expertise:
- A basic understanding of the RESTful API design
- Working knowledge of Spring Boot and Java 8
In addition, have at hand a Java IDE.
Setting Up a Cloudinary Account
First, if you don’t have one yet, sign up for a free Cloudinary account, which offers you credits for storage, transformations, and bandwidth. Alternatively, upgrade to a paid subscription for more credits and other features.
Enabling Unsigned Uploads
Next, enable unsigned uploads in your Cloudinary account’s default upload preset, after which you can upload media into the account’s Media Library without presigning upload requests.
Take the steps below to set up an upload preset, i.e., centrally configure your upload options, eliminating the need for specifying the configurations for each and every upload, and then enable the preset.
- On your Cloudinary account’s Dashboard, click Settings (the icon in the form of a gear at the top) and then the Upload tab, also at the top. Scroll down to the Upload presets section.
- Click Edit next to my-unsigned preset and, in the next screen, set Signing Mode to Unsigned.
Integrating Cloudinary Into a Spring Boot Application
The easiest way to integrate Cloudinary into a Spring Boot application is through Cloudinary’s Maven dependency. Follow the steps below.
-
In your application’s
pom.xml
file, add the Cloudinary dependency to the list of dependencies:<dependency> <groupId>com.cloudinary</groupId> <artifactId>cloudinary-http44</artifactId> <version>1.17.0</version> </dependency>
Create a bean method with the
@bean
method-level annotation, which will return your Cloudinary configuration. That way, you can apply the dependency configured in step 1 across your entire application.
In the main Application.java
class of your application, add the code snippet below. Be sure to replace the variables cloud_name
, api_key
, and api_secret
with their values, which are displayed on your Cloudinary account’s Dashboard.
@Bean
public Cloudinary cloudinaryConfig() {
Cloudinary cloudinary = null;
Map config = new HashMap();
config.put("cloud_name", cloudName);
config.put("api_key", apiKey);
config.put("api_secret", apiSecret);
cloudinary = new Cloudinary(config);
return cloudinary;
}
You can now use Cloudinary anywhere in your Spring Boot application.
Uploading Images
The code snippets below from the Spring Boot application referenced above enable you to upload images to Cloudinary with a top-down approach: RestController -> Service -> Application Properties. Ignore the lines that are commented out; they’re not relevant for this tutorial.
RestController
private final CloudinaryGifService cloudinaryGifService;
private final UserService userService;
@PostMapping("/gifs")
public ResponseEntity<LinkedHashMap<String, Object>> uploadGif(@RequestParam("gifFile")
MultipartFile gifFile, Authentication authentication, @RequestParam("title") String title) throws IOException {
// User currentUser =
// userService.findUserByEmail(authentication.getName()); // Authorization
String url = cloudinaryGifService.uploadFile(gifFile);
cloudinaryGifService.saveGifToDB(url, title , currentUser);
// LinkedHashMap<String, Object> jsonResponse = cloudinaryGifService.modifyJsonResponse("create", URL);
return new ResponseEntity<>(jsonResponse,HttpStatus.CREATED);
}
In the above code:
- The
cloudinaryGifService
variable instantiates an object of theCloudinaryService
class, which holds the logic that converts the uploadedMultipartFile
file to a regular file before uploading it to Cloudinary. - The
uploadGif
method accepts thegif
title andgif
image as aMultipartFile
file. - The
Service
class uploads the image to your Cloudinary account and then saves the image (gif
) URL and title to the database of the application.
{note}
gif
is specified in the code because the TeamWork API handles only images of the format type GIF (.gif
). In actual fact, this process works for image files of other formats, such as .png
, .jpeg
, etc.
{/note}
Service
Recall that the CloudinaryService
class contains the logic for converting and uploading images to Cloudinary. Here is the code in question:
private final Cloudinary cloudinaryConfig;
public String uploadFile(MultipartFile gif) {
try {
File uploadedFile = convertMultiPartToFile(gif);
Map uploadResult = cloudinaryConfig.uploader().upload(uploadedFile, ObjectUtils.emptyMap());
boolean isDeleted = uploadedFile.delete();
if (isDeleted){
System.out.println("File successfully deleted");
}else
System.out.println("File doesn't exist");
return uploadResult.get("url").toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private File convertMultiPartToFile(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
return convFile;
}
In the above code:
-
cloudinaryConfig
instantiates your Cloudinary configuration from the@bean
method you created earlier. -
uploadFile
convertsMultipartFile
to a normal file format with theconvertMultiPartToFile
method because interface MultipartFile represents an uploaded file received in a multipart request. Afterwards,uploadFile
uploads the file to Cloudinary and returns the GIF image’s URL for theRestController uploadFile
method. - The boolean
isDeleted
checks if the file was deleted after upload to ensure that no images are stored in your Spring Boot application’s file system.
To test the uploads with POSTMAN, follow the steps in the answers on this Stack Overflow page.
To upload images up to 10 MB in size, increase your application’s Spring servlet’s multipart file-size by adding this code to your application.properties
file:
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
Video Upload
To upload videos programmatically with Cloudinary, follow the same process for uploading images. Note that Cloudinary’s upload
method uploads files up to 100 MB only. For videos of a larger size, specify the upload_large method, which uploads large files to Cloudinary in chunks:
cloudinary.uploader().uploadLarge("my_large_video.mp4", ObjectUtils.asMap("resource_type", "video"));
Be sure to update the CloudinaryService
class and the uploadFile
method, like this:
public String uploadFile(MultipartFile gif) {
try {
File uploadedFile = convertMultiPartToFile(gif);
Map uploadResult = cloudinaryConfig.uploader().uploadLarge(uploadedFile, ObjectUtils.emptyMap());
boolean isDeleted = uploadedFile.delete();` \
if (isDeleted){
System.out.println("File successfully deleted");
}else
System.out.println("File doesn't exist");
return uploadResult.get("url").toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Also, raise the limit of spring.servlet.multipart.max-request-size
in your application.properties
file.
References
For further reference, check out the following: