Why choose Cloudinary for image uploads in Spring Boot? Well, it’s free (up to a point), fast, and takes care of all the boring stuff—like resizing, cropping, and optimizing—so you don’t have to. Plus, with its global CDN, your images load quicker than your developer fixing a “small bug”!
Initializing Spring Boot Project
Initialize a Spring Boot project if you haven’t using the following article:
getting started with spring boot
Setting up Cloudinary account and Environment variables
Go to the official Cloudinary website here!
Sign up using your account.
After signup and login, you will be at the homepage
Go to the dashboard and there, below the production environment tab, you will have your cloud name. Copy that cloud name and set it in the environment variables of your computer.
After copying the cloud name, we also want the API key and API secret. These will be obtained from the “go to API keys“ button.
Click on it and you will see those two values there. Add all three things in the environment variables, i.e cloud name, api key and api secret
To set the values in the environment variable, go to your system’s search bar:
Click on the edit environment variables → click on the environment variable at the bottom right → In the system variables section below, click on the new → put the variable name as “CLOUDINARY_CLOUD_NAME“ and put the variable value as the value that you obtained from the dashboard.
Do this for “CLOUDINARY_API_KEY“ and “CLOUDINARY_API_SECRET“. Make sure our names match because in the code below we will be using the names to get the key values.
Save the environment variables and restart your IDE.
Setting up the dependencies
Open your pom.xml file and copy the following two dependencies and refresh and sync the Maven:
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-http5</artifactId>
<version>2.0.0</version> <!--use the latest version-->
</dependency>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-taglib</artifactId>
<version>2.0.0</version> <!--use the latest version-->
</dependency>
Configuration file
Now we will have to set up a configuration class that will provide the Cloudinary bean to use later for uploading and destroying images.
Cross-check the value names in the @Value annotations; otherwise, you will get a compile-time error.
import com.cloudinary.Cloudinary;
import com.cloudinary.utils.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CloudinaryConfiguration {
@Value("${CLOUDINARY_CLOUD_NAME}")
private String cloudName;
@Value("${CLOUDINARY_API_KEY}")
private String apiKey;
@Value("${CLOUDINARY_API_SECRET}")
private String apiSecret;
@Bean
public Cloudinary cloudinary(){
return new Cloudinary(ObjectUtils.asMap(
"cloud_name", cloudName,
"api_key", apiKey,
"api_secret", apiSecret
));
}
}
Service class
Now let’s create a service class that will use the Cloudinary bean to upload or destroy an image. The class will have two methods.
Upload Image: This method will return the URL that you can use to retrieve the image and takes a MultipartFile image to upload in the cloud.
Destroy Image: This method will return a boolean value “true” when it deletes the image from the cloud using their URL.
import com.cloudinary.Cloudinary;
import com.cloudinary.utils.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Map;
@Service
public class CloudinaryService {
private final Cloudinary cloudinary;
public CloudinaryService(Cloudinary cloudinary) {
this.cloudinary = cloudinary;
}
public String uploadImage(MultipartFile image){
try {
Map uploadResult = cloudinary.uploader().upload(image.getBytes(),
ObjectUtils.asMap("resource_type", "image"));
return uploadResult.get("secure_url").toString();
}catch (IOException e){
throw new RuntimeException("Something went wrong with image upload: " + e.getLocalizedMessage());
}
}
public boolean destroyImage(String imageUrl){
try {
// Extract public_id from URL
String publicId = extractPublicId(imageUrl);
if (publicId == null) {
throw new IllegalArgumentException("Invalid Cloudinary image URL");
}
Map destroyResult = cloudinary.uploader().destroy(publicId, ObjectUtils.emptyMap());
return "ok".equals(destroyResult.get("result"));
}catch (Exception e){
throw new RuntimeException("Something went wrong with image destroy: " + e.getLocalizedMessage());
}
}
public String extractPublicId(String imageUrl){
String[] parts = imageUrl.split("/");
if (parts.length < 2) {
return null;
}
String filename = parts[parts.length - 1];
return filename.split("\\.")[0]; // Remove file extension (e.g., .jpg, .png)
}
}
Making a controller and testing in Postman
Let’s make two endpoints on which we can upload and destroy an image.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
public class CloudinaryController {
private final CloudinaryService cloudinaryService;
public CloudinaryController(CloudinaryService cloudinaryService) {
this.cloudinaryService = cloudinaryService;
}
@PostMapping("/upload")
public String uploadImage(
@RequestPart(name = "image")MultipartFile image
){
return cloudinaryService.uploadImage(image);
}
@DeleteMapping("/delete")
public ResponseEntity<Object> deleteImage(
@RequestParam(name = "imageUrl") String imageUrl
){
cloudinaryService.destroyImage(imageUrl);
return new ResponseEntity<>(null, HttpStatus.NO_CONTENT);
}
}
Now let’s quickly run the tests by uploading, viewing, and deleting the image:
Uploading image:
We will use form-data in the body to send the image file from our local device.
Copy the URL that we received from the response body. You can also set up your code to store this in an SQL database.
Viewing the image:
We will create another GET request and paste the previously obtained image URL directly in the URL box.
Deleting the image:
Now let’s create a DELETE request to delete the image using it’s URL.
So this is how we upload and destroy images using Spring Boot and Cloudinary. You can set up your code to store the URL in your database for future use of the uploaded image.
Happy coding! It’s 200!