Uploading Media in Spring Boot Programmatically With Cloudinary
Tags: java, springboot, cloudinary, tutorial
Published: 2022-01-08 19:24:03

Developers building software with media features must store the media somewhere and, in most cases, [transform](https://cloudinary.com/documentation/transformation_reference) 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]([https://github.com/Kikiodazie/Teamwork-API](https://github.com/Kikiodazie/Teamwork-API)).

## 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](https://cloudinary.com/users/register/free) 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](https://cloudinary.com/documentation/upload_presets), 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. 

1. 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. 
2. Click **Edit** next to my-unsigned **preset** and, in the next screen, set **Signing Mode** to **Unsigned**.

    
![Screenshot from 2022-01-05 01-39-58.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1641664328746/E314oH6L_.png)


## 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.

1. 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>


2. Create a [bean](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-introduction) 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 the ``CloudinaryService`` class, which holds the logic that converts the uploaded ``MultipartFile`` file to a regular file before uploading it to Cloudinary.
* The ``uploadGif`` method accepts the ``gif`` title and ``gif`` image as a ``MultipartFile`` 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`` converts ``MultipartFile`` to a normal file format with the ``convertMultiPartToFile`` method because [interface MultipartFile](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html) represents an uploaded file received in a [multipart request](https://stackoverflow.com/questions/16958448/what-is-http-multipart-request). Afterwards, `uploadFile`  uploads the file to Cloudinary and returns the GIF image’s URL for the `RestController 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](https://stackoverflow.com/questions/39660074/post-image-data-using-postman).

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](https://cloudinary.com/documentation/upload_images#chunked_asset_upload) 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:

* [Cloudinary’s documentation on image and video uploads](https://cloudinary.com/documentation/java_image_and_video_upload)
* [Teamwork API on GitHub](https://github.com/Kikiodazie/Teamwork-API)