Upload files directly to Cloudinary from a React application

Upload files directly to Cloudinary from a React application

Introduction

Cloudinary is a SaaS technology company that provides a cloud-based image and video management services. It enables users to upload, store, manage, manipulate, and deliver images and video for websites and apps

image2 1.png

The most common approach to uploading files directly to cloudinary would be to first upload to the server e.g Node.js, Go, PHP then from the server upload to cloudinary. In this article we will learn how to upload directly to cloudinary using React hereby eliminating the need to first send the file to the server. PS: This approach can also be used with any other technology and not just react

Prerequisites

  • Code editor that supports JS (preferable VS code)
  • Cloudinary account
  • Knowledge of React JS
  • Familiar with cloudinary dashboard

Why upload to cloudinary directly?

As stated earlier, the most common way through which media files are uploaded to cloudinary directly would be to first send to the server then upload to cloudinary. This approach can be improved if we can remove the first step of sending to the server and rather send to the cloudinary directly from the front end. For Example, Imagine we want to upload a 10mb image but first upload to the server which will take let’s say 10 seconds, then the server uploads the 10mb images again to cloudinary which takes another time. The point of this new approach is to eliminate the need to upload first to the server which will not just save us resources but also save us time and improve user experience.

image4.png

Cloudinary setup

Before uploading directly to cloudinary you need to setup the your cloudinary account to accept uploads directly. Below are the steps

Step 1: Login to cloudinary

image5.png

Step 2: Go to settings/ upload

image6.png

Step 3: Scroll down and click on “add upload preset”

image3.png

Step 4: Fill out the form

  • Fill out the preset and folder name.
  • Change “signed mode” to unsigned upload
  • Note: “folder” is the name of the folder the files will be uploaded to.

image1.png

Step 5: Copy preset name and api key

In your dashboard copy your API and the name of the just created preset name. It will be needed to make the direct upload using axios.

image7.png

Save the copied key and preset name and proceed to the next section

Uploading using react

After the above steps have been completed the next step would be to upload a file directly to cloudinary directly from your react app. To achieve this we follow the steps below.

Note: You should already have your react app setup to follow this steps

Step 1: Create file input component

const FileInput = () => {
 return <input type="file" onChange={()=>{}} />;
};

export default FileInput;

Step 2: Add an onChange handler to handle input change

const FileInput = () => {
   const onChangeHandler = ({target:{files}}) => {
     handleUploadImages({files);
   };
   return <input type="file" onChange={onChangeHandler} />;
};

Step 3: Add function to upload to cloudinary

This function will upload the selected file to cloudinary directly using axios.

const handleUploadImages = async (images) => {
   try {
     const uploads = images.map(async (image) => {
       try {
         const formData = new FormData();
         formData.append('file', image);
         formData.append('tags', `tutorial`);
         formData.append('upload_preset', 'tutorial'); 
         formData.append('api_key', 'API_KEY'); 
         formData.append(
           'timestamp',
           // eslint-disable-next-line newline-per-chained-call
           moment().utcOffset('+0100').format('LLLL')
         );

         const uploadResponse = await Axios.post(

      'https://api.cloudinary.com/v1_1/CLOUDINARY_USERNAME/image/upload',
           formData,
           { headers: { 'X-Requested-With': 'XMLHttpRequest' } }
         );
         return uploadResponse;
       } catch (err) {
         return console.log(err);
       }
     });

     const uploadResponses = await Axios.all(uploads);

     console.log(uploadResponses);
   } catch (err) {
     return console.error(err);
   }
 };

From the code above you can see that some values are appended to the form data before uploading.

  • upload_preset: This is the name of the upload preset that was created on cloudinary in step 3 and 4.
  • api_key: This is the api key on your cloudinary dashboard
  • tags: This is the tags that can be used to sort the image in your cloudinary dashboard. The value can be anything. In this case we call it “tutorial”
  • file: This is the file to be uploaded
  • timestamp: This is simply the time the picture was uploaded. In the case we used moment JS to get the time

If noticed above we mapped over the selected files and uploaded each individually this is in cases of multiple file uploads. Then we used Axios.all() to send all request simultaneously without having to wait for one to finish before the next one starts

const handleUploadImages = async (images) => {
   try {
     const uploads = images.map(async (image) => {
          // do things on things here
     });

     const uploadResponses = await Axios.all(uploads);

     console.log(uploadResponses);
   } catch (err) {
     return console.error(err);
   }
 };

After the above steps your component should look like this

import Axios from 'axios';
import moment from 'moment';


const FileInput = () => {
 const handleUploadImages = async (images) => {
   try {
     const uploads = images.map(async (image) => {
       try {
         const formData = new FormData();
         formData.append('file', image);
         formData.append('tags', `product`);
         formData.append('upload_preset', 'tutorial'); // this is yout upload opreset
         formData.append('api_key', 'API_KEY'); // This is your upload key
         formData.append(
           'timestamp',
           // eslint-disable-next-line newline-per-chained-call
           moment().utcOffset('+0100').format('LLLL')
         );

         const uploadResponse = await Axios.post(
           'https://api.cloudinary.com/v1_1/CLOUDINARY_USERNAME/image/upload',
           formData,
           { headers: { 'X-Requested-With': 'XMLHttpRequest' } }
         );
         return uploadResponse;
       } catch (err) {
         return console.log(err);
       }
     });

     const uploadResponses = await Axios.all(uploads);

     console.log(uploadResponses);
   } catch (err) {
     return console.error(err);
   }
 };

 const onChangeHandler = ({target: {files}}) => {
   handleUploadImages(files);
 };

 return <input type="file" onChange={onChangeHandler} />;
};

export default FileInput;

You can then send the return object from cloudinary to your server and the most important fields are secure_url and public_id. Of which you can used public_id for complex transformations and secure_url to access the image barebones. You will also find other fields there which you might find useful.

Conclusion

Uploading directly to cloudinary by first sending to the server is a good approach but it can be better optimized by uploading directly to cloudinary whilst eliminating the need to first upload to the server first then from server to cloudinary. This helps save resource and gives a better user experience as time for file uploads will be reduced by a great percentage.