Upload Image to Cloudinary

Upload Image to Cloudinary

The uploadImagesToCloudinary utility simplifies the Cloudinary image upload process, offering range of configuration options and prompt error detection with clear messaging.

Let's first dive into an example. Afterward, we'll delve deeper into the syntax and configuration options of the uploadImagesToCloudinary utility:

// import express and anything else that you need
// import "uploadImagesToCloudinary"  from 'express-cloudinary-image-handler'
 
const app = express()
 
app.post('/upload-images', async (req, res) => {
 
    try {
 
        const upload_report = await uploadImagesToCloudinary({
            req: req,
            configuration: {
                formDataFieldName: 'productImages',
                cloudinaryFolderName: 'product',
                allowedExtensions: ['png', 'jpg', 'jpeg'],  // Optional
                maxFileSizeInKB: 512, // Optional
                maxNumberOfUploads: 10, // Optional
                deleteAllTempFiles: true // Optional
            }
        })
 
        if (upload_report.isError) {
            return res.json({
                status_code: upload_report.errorInfo.statusCode,
                message: upload_report.errorInfo.message
            })
        }
 
        return res.json({
            message: 'Uploaded Images Successfully',
            info: {
                uploaded_images_info: upload_report.imagesInfo
            }
        })
    } 
    
    catch (error) {
        return res.json({ message: "Something went wrong" });
    }
})

uploadImagesToCloudinary - Parameters

Parameter NameTypeRequirementDescription
reqobjectRequiredThe Express request object.
configurationobjectRequiredConfiguration options for the upload.

configuration Object Properties:

Property NameTypeRequirementDescription
formDataFieldNamestringRequiredThe field name used in the frontend's FormData object for sending the image files to the backend.
cloudinaryFolderNamestringRequiredThe folder name in Cloudinary where the image will be stored.
allowedExtensionsarrayOptionalList of allowed file extensions for the image.
maxFileSizeInKBnumberOptionalMaximum allowed file size for the image in kilobytes.
maxNumberOfUploadsnumberOptionalMaximum number of images that can be uploaded at once.
deleteAllTempFilesbooleanOptionalDetails

uploadImagesToCloudinary - Return Value

Field NameTypeDescription
isErrorbooleanIndicates if there was an error during the upload.
errorInfoobjectContains error details if isError is true.
imagesInfoarrayArray containing information about each uploaded image.

errorInfo Object Properties:

Property NameTypeDescription
statusCodenumberThe status code of the error.
messagestringThe error message.

imagesInfo is an array of objects, where each object represents details about an uploaded image. Properties of each object:

Property NameTypeDescription
imageSrcstringThe direct URL or source of the uploaded image, which can be used to display or access the image.
imagePublicIdstringThe unique identifier provided by Cloudinary for the image. This ID is essential for delete operation.

uploadImagesToCloudinary - Multiple Instances

In some scenarios, you may need to use the uploadImagesToCloudinary utility more than once within the same controller.

To do this effectively, you should set the deleteAllTempFiles property to false. This ensures that image files uploaded under different field names are not deleted after the first instance completes its operation.

Here's an example:

// import express and anything else that you need
// import "uploadImagesToCloudinary"  from 'express-cloudinary-image-handler'
 
const app = express()
 
app.post('/upload-product-images', async (req, res) => {
 
    try {
 
        // First Instance: Upload Main Product Display Images
        const featuredImagesUploadReport = await uploadImagesToCloudinary({
            req: req,
            configuration: {
                formDataFieldName: 'featuredImages',
                cloudinaryFolderName: 'product',
                allowedExtensions: ['png', 'jpg', 'jpeg'],
                maxFileSizeInKB: 512,
                maxNumberOfUploads: 10,
                deleteAllTempFiles: false  // Important
            }
        })
 
        // Handle errors for the first instance
        if (featuredImagesUploadReport.isError) {
            return res.json({
                status_code: featuredImagesUploadReport.errorInfo.statusCode,
                message: featuredImagesUploadReport.errorInfo.message
            })
        }
 
        // Second Instance: Upload Product Detail/Angle Images
        const productImagesUploadReport = await uploadImagesToCloudinary({
            req: req,
            configuration: {
                formDataFieldName: 'productImages',
                cloudinaryFolderName: 'product',
                allowedExtensions: ['png', 'jpg', 'jpeg'],
                maxFileSizeInKB: 512,
                maxNumberOfUploads: 10,
                deleteAllTempFiles: true // Now it's safe to delete
            }
        })
 
        // Handle errors for the second instance
        if (productImagesUploadReport.isError) {
            return res.json({
                status_code: productImagesUploadReport.errorInfo.statusCode,
                message: productImagesUploadReport.errorInfo.message
            })
        }
 
        // Success Response
        return res.json({
            message: 'Uploaded Images Successfully',
            info: {
                featuredImages: featuredImagesUploadReport.imagesInfo,
                productImages: productImagesUploadReport.imagesInfo
            }
        })
    } 
    
    catch (error) {
        return res.json({ message: "Something went wrong" })
    }
})

In this example, the first instance uploads main product display images with the field name featuredImages and the second instance uploads product detail or angle images with the field name productImages. The deleteAllTempFiles property is set to false in the first instance to retain the images for the second instance. In the second instance, it's set to true to clean up all temporary files after the operation is complete.

deleteAllTempFiles Property - Details

The deleteAllTempFiles is a property within the configuration parameter. It's optional, and its default value is set to true.

What It Does

This property controls the cleanup behavior for files temporarily stored in the server's "temp" folder during the upload process.

  • When true: All files in the "temp" folder associated with the current upload operation, irrespective of their field names, are automatically deleted after the upload is complete. This ensures a clean temporary storage specific to the current operation, free from any residual files.

  • When false: The utility will delete all image files that match the name set in formDataFieldName and any non-image files from the "temp" folder. However, it will retain image files that have different field names than the one specified in formDataFieldName.

Use Cases

  • Set to true: Use this setting when you're uploading a batch of images in one go and want to ensure that the temporary storage is completely cleared afterward, leaving no leftover or unwanted files.

  • Set to false: Opt for this when you have multiple separate upload operations within the same controller. It ensures that files required for subsequent operations aren't mistakenly deleted by earlier tasks.

Naming Images in Cloudinary: Use Original Source File Name or Manually Set the Name

Is this seciton for you?

  • In prior sections, discussions regarding file naming were put aside, as image names in cloudinary were generated automatically.

  • With image names produced through the automatic process, you find out the image's name only after its upload.

  • However, if you need to determine the image's name before sending it to Cloudinary, this section is for you.

We've touched on the uploadImagesToCloudinary function, which requires a configuration parameter. This parameter is an object composed of several properties. All of these properties have been previously explained, except one: the useSourceFileName property.

This property is optional, accepting a boolean value with a default of false.

When set to true, the property allows the original source file name to be used as the Cloudinary image file's name.

Manually Set the Name

While using useSourceFileName, we can also manually set Name. This can be achieved by manipulating the frontend's FormData. Specifically, by providing a third parameter to the FormData, you can set the desired name for the image.

For instance:

formData.append('image', 'image_file', 'desired_image_name');

In this example, desired_image_name will be the name assigned to the image when it's uploaded to Cloudinary.

Ensuring Unique File Names

One of the primary concerns of using the original file name is the potential risk of overwriting an existing image in Cloudinary. If a new image, bearing the same name as an existing one, is uploaded, the older image will be replaced. This can lead to unintentional replacements and potential data loss.

To mitigate the risk of overwriting files in Cloudinary due to name collisions, it's advisable to ensure that each file name is unique. One effective way to achieve this is by leveraging packages like nanoid to generate a unique identifier for each file. By appending or prepending this unique ID to the original file name, the chances of having two files with the same name become extremely low.

For example:

import { nanoid } from 'nanoid';
 
// Generate a unique ID
const uniqueID = nanoid();
 
// Append the unique ID to the original file name
const uniqueFileName = `${uniqueID}_${image_info.img_file.name}`;
 
formData.append('image', image_name, uniqueFileName);

By adopting this approach, you not only retain the advantage of pre-determining the image's name before uploading but also ensure that each image has a distinct name, safeguarding against unintentional overwrites.