Codementor Events

Uploading Images to Cloudinary Using Multer and ExpressJS | by okpukoro joe | Medium

Published Dec 12, 2020
Uploading Images to Cloudinary Using Multer and ExpressJS | by okpukoro joe | Medium

File upload has become a common feature in every web application, many tutorials you’ll find on the web will only show you how you can upload files to your application’s database and you get stuck when you’re trying to upload your images to a cloud service like Cloudinary and Amazon S3. During the course of this tutorial, we’ll be using Cloudiary for storing our images, we will then save the link to that image to our database instead of the entire image buffer.

In this article, I’ll be showing what Cloudinary and Multer does and how easy it is to work with them whether you’re working on API for a Single Page Application, or building a monolithic application this tutorial got you covered.

Before we proceed, I’ve set up an empty ExpressJS application with support for ES6+ so that we can focus more on the file upload feature, you can access it from here.
Let’s begin by first knowing the use of Cloudinary.

What is Cloudinary

Cloudinary is an end-to-end image management solution for your website and mobile apps. Cloudinary covers everything from image uploads, storage, manipulations, optimizations to delivery.
You can easily upload images to the cloud, automatically perform smart image manipulations without installing any complex software. All your images are then seamlessly delivered through a fast CDN, optimized and using industry best practices.
Cloudinary offers comprehensive APIs and administration capabilities and is easy to integrate with new and existing web and mobile applications.
You can learn more about cloudinary here

To get started, create/sign to your Cloudinary account, on your dashboard you should see your account details like this.

1*HZHM1JqkUsbK_zLF5UBl_g.png

On the root directory of your application, there’s a sample.env file that contains all the environment variables we’ll be using for this application. You should see something like this.
Create a .env file on the root directory of your application, copy all the variable names and replace the values with your Cloudinary info.
Let’s install the Cloudinary package that will allow us to interface with the Cloudinary API npm install cloudinary.
Now to finish up the Cloudinary setup process, On your server/ directory, create a config/ folder, and a file named cloudinaryConfig.js. This directory will contain the configuration you’ll need to upload files to Cloudinary. When you’re done, your directory should now look like this.

1*PHZr62zwNHYgN0bVO2KgbA.png
On the cloudinaryConfig.js file, configure the package to use our Cloudinary credentials with the block of code below.

const cloudinaryConfig = () => config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
export { cloudinaryConfig, uploader };

Great!!! Cloudinary has been set up successfully on your application, we can now proceed to upload files with the aid of multer.

What Is Multer?

npm i multer

Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency.

Why Is it Needed?

Out of the box, NodeJS doesn’t know how to process any data, for example, we wanted our application to process JSON requests, we had to body-parse, in this case, multer makes it possible for an application to accept form-data which allows us to easily transport files from the browser to our server.
https://www.npmjs.com/package/multer

Without multer, when you’re sending a files to your server, the request body object(req.body) will be empty. Multer allows the data you’re sending from a form to be available and it also creates a req.file object which gives us access to the file buffer we’ve just uploaded from the client-side.
Now let’s configure Multer as a middleware that we can use with any route that needs to upload an image. On the middleware folder, create a multer.js file with the following configuration.

import multer from ‘multer’;
const storage = multer.memoryStorage();
const multerUploads = multer({ storage }).single(‘image’);
export { multerUploads };

Notice that we’re making use of memory storage instead first writing the file to an upload/ directory, this is because when we deploy our application to Heroku, we may not have the adminitrative privileges to write files to the remote computer which may crash our entire application.
multer.memoeryStorage() tells multer that we’ll save the file to memory first which can be manipulated to the suit any purpose.
multer({ storage }).single('image'); sets the storage option we’ll be using on the application while the .single('image'); specifies the field name multer should go to when it’s looking for the file.
Now it’s all set, let’s try to use multer and Cloudinary to upload an image.
Import multerUploads on your server/index.js and add the following block of code to your server/index.js file

app.post('/upload', multerUploads, (req, res) => {
console.log('req.body :', req.body);
});

Now open postman on the body section, select forma-data and enter the field name you used in your multer configuration which in our case was image. Your postman should look like this, now click on send.

1*a0I6VdMqvhBpycckfR32oQ.png

Notice it logs an empty object on the console.

1*ICoP1AENXUKMvHLEIXyWPw.png

Now on the fieldname "image", change the type textto file just as in the screenshot above, you should have something similar to this.
1*7HD8z8AL8Mtn5k8qFZO_JA.png

On the upload route, change console.log(‘req.body :’, req.body); to console.log('req.file : ' req.file); go back to postman, and select an image, hit the send button and you should have something like this

1*AU7d_f630cSg39NqU4bg7Q.png

Congratulations multer is now working as a middleware, we can go ahead and use it on our entire application, but for the sake of this article, we’ll only call multer on the routes we need it.
But I want to you to notice that the file is coming as buffer because we’re pushing it to memory before we can upload it to Cloudinary, which pose an issue for us since the Cloudinary uploader is either expecting a file path or a string but we’re receiving a buffer from multer.

So let’s convert the buffer to the format that the Cloudinary uploader will understand, we’re going to use thedatauri package.

What Is a Data URI?

A data URI is a base64 encoded string that represents a file. Getting the contents of a file as a string means that you can directly embed the data within your HTML or CSS code. When the browser encounters a data URI in your code, it’s able to decode the data and construct the original file. Learn more

npm i datauri to add the package and then update your multer setup to look like this.

import multer from 'multer';
import Datauri from 'datauri';
import path from 'path';
const storage = multer.memoryStorage();
const multerUploads = multer({ storage }).single('image');
const dUri = new Datauri();
/**
* @description This function converts the buffer to data url
* @param {Object} req containing the field object
* @returns {String} The data url from the string buffer
*/
const dataUri = req => dUri.format(path.extname(req.file.originalname).toString(), req.file.buffer);
export { multerUploads, dataUri };

On the dataUri function above, we pass the request object and format the buffer and return a string blob.
It’s time to add the Cloudinary uploader to the application, but first let’s make some modification on the configuration function, it’s best we convert it to a middleware so that we don’t have to invoke it everytime we want to use the Cloudinary settings.
Your new Cloudinary config should look be like this.

import { config, uploader } from 'cloudinary'
import dotenv from 'dotenv';
dotenv.config();
const cloudinaryConfig = (req, res, next) => {
config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
next();
}
export { cloudinaryConfig, uploader };

Notice I added a new package called dotenv it allows us load the settings on our .env file into the node application process.
npm i dotenv , update your server/index.js to look like this.

import express from 'express';
import { urlencoded, json } from 'body-parser';
import { resolve } from  'path';
import { uploader, cloudinaryConfig } from './config/cloudinaryConfig'
import { multerUploads, dataUri } from './middlewares/multerUpload';
const app = express();
const Port = process.env.PORT || 3000;
app.use(express.static(resolve(__dirname, 'src/public')));
app.use(urlencoded({ extended: false }));
app.use(json());
app.use('*', cloudinaryConfig);
app.get('/*', (req, res) => res.sendFile(resolve(__dirname, '../public/index.html')));
app.post('/upload', multerUploads, (req, res) => {
if(req.file) {
const file = dataUri(req).content;
return uploader.upload(file).then((result) => {
const image = result.url;
return res.status(200).json({
messge: 'Your image has been uploded successfully to cloudinary',
data: {
image
}
})
}).catch((err) => res.status(400).json({
messge: 'someting went wrong while processing your request',
data: {
err
}
}))
}
});
app.listen(Port, () => console.log(`Server started at http://localhost:${Port}`));

Open postman again, select a file and click send you should get this message
1*SDYCtOfSKsm27JrdaIvyIQ.png

you can now save the image URL to your database.
Congratulations, you just learn how to upload files to Cloudinary using multer.
I hope this was helpful, please leave your thoughts in the comment section below.

Discover and read more posts from Jehonadab Okpukoro
get started