Using Cloudinary to manage media files(images and videos) for your Node.js application
Images and videos have become an integral part of websites, web applications and mobile applications. They are usually used to pass messages across to users and in some cases add to the sites aesthetics. Optimization of these media files for users especially in terms of speed of delivery can be resource intensive for developers. Third party CDNs like Cloudinary help solve this problem.
Cloudinary provides an end to end Image and video management solution that enables quick media upload and download, cloud storage for media files, a powerful media administration, media transformation (dynamically resize, crop etc) and a worldwide content delivery network for fast delivery of media files.
In this article I would be breaking down the steps of using the Cloudinary API documentation to connect your RESTFul NodeJs API to Cloudinary for image upload and retrieval. I recently faced this challenge while developing an API for a shopping app that allows merchant Add, Edit, View and delete products. The project can be found here.
There are several ways to access uploaded files in an express app, however in this project express file upload middleware was used. Express file upload package can be added using npm or yarn depending on your preference.
//Install Express fileupload npm install --save express-fileupload
Temporary files can be used to manage the upload process instead of memory. To achieve this, in the app entry file(app.js in this case) we setup the express fileupload middleware to use temporary files and save them in a temporary file directory.
// Setup express fileupload in the app.js fileapp.use(
fileUpload({
useTempFiles: true,
tempFileDir: '/tmp/'
})
)
Media files uploaded to Cloudinary are saved on your personal cloud account which can be created on the Cloudinary website. To connect to app to your cloudinary cloud account, the cloudinary package needs to be added and configured with the following credentials that are available on your dashboard Cloud name, API Key, and API Secret, or by simply using the Environment variable string in the .env file
// Install cloudinary
npm install cloudinary// Cloudinary config credentials in .env fileCLOUDINARY_URL = cloudinary://{API Key}:{API Secret}@{Cloud name}
According to the Cloudinary API documentation the cloudinary uploader method expects three parameters — the file to be uploaded, options(like where in your cloud account the file should be uploaded to ) and a callback(on upload success or error).
cloudinary.v2.uploader.upload(file, options, callback);
As a personal preference especially when dealing with functions that would be used more than once through out the application, I maintain a separate file that i name helper.js to hold all of these functions. In this file a function to manage image upload is defined as follows:
const cloudinary = require('cloudinary').v2;uploadToCloudinary(image){return new Promise((resolve, reject) => {
cloudinary.uploader.upload(image.tempFilePath,(err, url) =>{
if(err) return reject(err);
return resolve(url);
})
})
}
By using Promises we asynchronously allow the upload process to run while running other processes within the app and resolve the promise when we get a response. Thanks to the express fileupload package we added initially, the image can be accessed from ‘req.files’. When this function is called in our post route, we can access the Cloudinary upload response and store in a variable.
image_uploaded = await Helper.uploadToCloudinary(req.files.image)
The response from above would usually look like this:
{
public_id: 'SCA/myqlweye1bals0yjkhaj',
version: 1585575042,
signature: 'f8d17176aa8b0af991df37194d1bae43a7235370',
width: 800,
height: 800,
format: 'jpg',
resource_type: 'image',
created_at: '2020-03-30T13:30:42Z',
tags: [],
bytes: 36370,
type: 'upload',
etag: '0b2ea4e626063b289e128da5c89b144b',
placeholder: false, url:'http://res.cloudinary.com/oluwamayowaf/image/upload/v1585575042/SCA/myqlweye1bals0yjkhaj.jpg',
secure_url:'https://res.cloudinary.com/oluwamayowaf/image/upload/v1585575042/SCA/myqlweye1bals0yjkhaj.jpg',
original_filename: 'tmp-1-1585575033858'
}
We have successfully uploaded this image https://res.cloudinary.com/oluwamayowaf/image/upload/v1585575042/SCA/myqlweye1bals0yjkhaj.jpg to Cloudinary and can use it within the app as needed .The url or secure_url properties holds the exact location of the uploaded file on the Coudinary cloud account, while the public_id property holds the name of the uploaded file on the Cloudinary cloud account. The url property can then be saved on the database at this point, by assessing it with image_uploaded.url. To perform multiple operations on the image though it might be preferable to store the public_id in the database. This allows us to easily perform functions like deleting the image from the Cloudinary account.
To delete images from the Cloudinary account the Destroy method is used from the Cloudinary API.
cloudinary.v2.uploader.destroy(public_id, options, callback);
The destroy method requires the public_id to be able to delete the file from the cloud account. Other than that it has a very similar structure to the upload method.
The full code to the project referred to in this article can be found on Github.