DEV Community

mahiuddinTuhin
mahiuddinTuhin

Posted on

Understanding the File Upload Middleware with Cloudinary in Node.js

In this article, we will explore a middleware for file uploads in a Node.js application, which leverages Cloudinary for image storage. The middleware is written in TypeScript and uses the multer library for handling multipart/form-data, which is primarily used for uploading files.

Setting Up Cloudinary

Cloudinary is a cloud-based service that provides an end-to-end solution for image and video management, including uploads, storage, manipulations, optimizations, and delivery.

The Cloudinary configuration is set up at the beginning of the code:

cloudinary.config({
  cloud_name: config.CLOUD_NAME,
  api_key: process.env.API_KEY,
  api_secret: process.env.API_SECRET,
});
Enter fullscreen mode Exit fullscreen mode

The cloud_name is your unique Cloudinary account identifier. The api_key and api_secret are your Cloudinary account credentials, which should be kept secure and not exposed in your code.

The Upload Function

The uploadToCloudinary function is responsible for uploading a file to Cloudinary:

const uploadToCloudinary = (path: string, imageName: string) => {
  // ...
};
Enter fullscreen mode Exit fullscreen mode

This function takes two parameters: the local path of the image to be uploaded (path) and the desired public ID for the image on Cloudinary (imageName). If the path is not provided, an error is thrown.

The function returns a Promise that resolves with the result of the upload or rejects with an error. After the upload is complete, the local file is deleted using the fs.unlink function.

Multer Middleware

Multer is a middleware for handling multipart/form-data, which is primarily used for uploading files. It is used to process the incoming request and store the uploaded files in the local filesystem.

The storage object defines where to store the uploaded files and how to name them:

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, process.cwd() + "/uploads/");
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() *  1e9);
    cb(null, file.fieldname + "-" + uniqueSuffix);
  },
});
Enter fullscreen mode Exit fullscreen mode

The destination function determines the folder where the uploaded files will be stored. The filename function generates a unique name for each uploaded file.

Finally, the upload middleware is created using the defined storage:

export const upload = multer({ storage: storage });
Enter fullscreen mode Exit fullscreen mode

This middleware can now be used in an Express route to handle file uploads. When a file is uploaded, it will be stored in the specified directory and then uploaded to Cloudinary.

Code at a glance

/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-var-requires */
import { v2 as cloudinary } from "cloudinary";
import multer from "multer";
import config from "../config";
import AppError from "../errors/customError";
const fs = require("fs");

cloudinary.config({
  cloud_name: config.CLOUD_NAME,
  api_key: process.env.API_KEY,
  api_secret: process.env.API_SECRET,
});

const uploadToCloudinary = (path: string, imageName: string) => {
  if (!path) {
    throw new AppError("File path does not found!", 400);
  }

  return new Promise((resolve, reject) => {
    try {
      cloudinary.uploader.upload(
        path, //local image path
        { public_id: imageName },
        function (error, result) {
          if (error) {
            reject(error);
          }
          resolve(result);

          // removing image file from 'path' of image
          fs.unlink(path, (err: any) => {
            if (err) {
              throw new AppError("Error in deleting file after uploads", 400);
            }
          });
        },
      );
    } catch (error: any) {
      throw new AppError(error.message, 400);
    }
  });
};

export default uploadToCloudinary;

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, process.cwd() + "/uploads/");
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
    cb(null, file.fieldname + "-" + uniqueSuffix);
  },
});

export const upload = multer({ storage: storage });

Enter fullscreen mode Exit fullscreen mode

Conclusion

This middleware provides a robust solution for handling file uploads in a Node.js application. By integrating Cloudinary, it offloads the responsibility of storing and serving images, allowing the application to focus on other tasks. The use of Promises and async/await makes the code easier to read and understand, and the use of multer simplifies the handling of file uploads.

Top comments (0)