Cloudinary is a cloud service built using AWS S3 that makes image and video storage and management easy and convenient.
In this article we will cover uploading, retrieving, and deleting images from Cloudinary.
Create a project folder, open that folder and initiate a node there.
1 2 3
mkdir cloudinary - tutorial cd cloudinary - tutorial npm init - y
Install npm packages required to build the application. For this article we are installing
Cloudinary (npm package to manage Cloudinary inside a node application)
Express
Mongoose (to manage MongoDB database)
Dotnev (to configure and use environment variables).
Multer (for file upload)
npm i -S cloudinary express mongoose multer dotenv
Install nodemon npm package as dev-dependency.
npm i -D nodemon
Create server file app.js and setup initial server as follows,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const express = require("express");
const app = express();
const mongoose = require("mongoose");
require("dotenv")
.config();
//Connect to database
try {
mongoose.connect("mongodb://localhost:27017/cloudinary", {
useUnifiedTopology: true,
useNewUrlParser: true
});
console.log("connected to db");
} catch (error) {
handleError(error);
}
process.on('unhandledRejection', error => {
console.log('unhandledRejection', error.message);
});
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({
extended: true
}));
app.listen(process.enve.PORT || 8080, function () {
console.log("App running!");
});
Create .env file and store your port in format
PORT=port_number
Now, check that everything is working fine. Start your application by typing command in a separate terminal.
nodemon app.js
Note: make sure that MongoDB server is already running on your system if you are not using the cloud version.
You will receive a response in the terminal as:
Now let’s create a user model using Mongoose.
Create models directory and a file named user.js in that directory. Create user model as:
1 2 3 4 5 6 7
const mongoose = require("mongoose"); const userSchema = new mongoose.Schema({ name: String, profile_img: String, cloudinary_id: String }); module.exports = mongoose.model("User", userSchema);
Here we have defined three fields for each user, name, profile_img, and cloudinary_id.
Now Visit Cloudinary and login/register. Visit your dashboard and you will notice your credentials as:
Copy Cloud_name, API_key, and API_secret and store them in .env file.
1 2 3
CLOUD_NAME = YOUR - CLOUD - NAME API_KEY = YOUR - API - KEY API_SECRET = YOUR - API - SECRET
Create a folder named utils and and create two files, multer.js and cloudinary.js, in it.
Open cloudinary.js and write down the code.
1 2 3 4 5 6 7 8
const cloudinary = require("cloudinary") .v2; cloudinary.config({ cloud_name: process.env.CLOUD_NAME, api_key: process.env.API_KEY, api_secret: process.env.API_SECRET, }); module.exports = cloudinary;
Then you need to set up multer to facilitate file upload. Open multer.js and write code as,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const multer = require("multer");
const path = require("path");
// Multer config
module.exports = multer({
storage: multer.diskStorage({}),
fileFilter: (req, file, cb) => {
let ext = path.extname(file.originalname);
if (ext !== ".jpg" && ext !== ".jpeg" && ext !== ".png") {
cb(new Error("Unsupported file type!"), false);
return;
}
cb(null, true);
},
});
Here we are setting up multer to check for incoming file extensions and make sure we are only passing .jpg or .jpeg or .png. If that is not the case it gives an error with the message “Unsupported file type!”.
Now let’s set up an endpoint where your server will be listening to the requests. Create a routes folder and user.js file in there, import this file in app.js, and paste this line above app.listen() in app.js.
app.use("/user",userRoutes);
Open file routes/user.js and write down code,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const router = require("express")
.Router();
const cloudinary = require("../utils/cloudinary");
const upload = require("../utils/multer");
const User = require("../models/User");
router.post("/", upload.single("image"), async (req, res) => {
try {
// Upload image to cloudinary
const result = await cloudinary.uploader.upload(req.file.path);
// Create new user
let user = new User({
name: req.body.name,
profile_img: result.secure_url,
cloudinary_id: result.public_id,
});
// save user details in mongodb
await user.save();
res.status(200)
.send({
user
});
} catch (err) {
console.log(err);
}
});
module.exports = router;
Here we have defined only one POST route which can be used to create a new user. Before saving the user to MongoDB we are using multer to process the file and then Cloudinary to upload that file and provide us with secure_url and public_id in return, which we will store in the database for future use.
Let’s test this endpoint. Create POST request in Postman to endpoint localhost:8080/user.
The response is user object saved to the database and is the correct response. You can verify by visiting the media tab of your Cloudinary account and also by checking your database. You can use a secure url directly where you need it such as html or ejs files.
Now let’s add GET route to retrieve a user image. We can directly pull it from the database. Add the given code to routes/app.js.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
router.get("/:id", async (req, res) => {
try {
let user = await User.findbyId(req.param.id);
if (!user)
res.status(404)
.send({
message: "User not found!"
});
res.status(200)
.send(JSON(user));
} catch (err) {
console.log(err);
}
});
This route receives the id of the user as a request parameter and retrieves information about the user if it exists in the database. Otherwise it responds with an error message.
You can test this endpoint by requesting localhost:8080/user/id.
Replace this id with the response _id you received at the last request. The received response for this request should be the same as the above request in the case of valid id.
Deletion can be performed as:
1 2 3 4 5 6 7 8 9 10 11 12 13
router.delete("/:id", async (req, res) => { try { // Find user by id let user = await User.findById(req.params.id); // Delete image from cloudinary await cloudinary.uploader.destroy(user.cloudinary_id); // Delete user from db await user.remove(); res.json(user); } catch (err) { console.log(err); } });
An update option is not provided by Cloudinary under cloudinary.uploader so updating is done by first deleting and then uploading a new image and modifying the user profile in the database accordingly within the same route. Code for PUT route is as follows,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
router.put("/:id", upload.single("image"), async (req, res) => { try { let user = await User.findById(req.params.id); // Delete image from cloudinary await cloudinary.uploader.destroy(user.cloudinary_id); // Upload new image to cloudinary const result = await cloudinary.uploader.upload(req.file.path); const data = { name: req.body.name || user.name, profile_img: result.secure_url || user.profile_img, cloudinary_id: result.public_id || user.cloudinary_id, }; user = await User.findByIdAndUpdate(req.params.id, data, { new: true }); res.json(user); } catch (err) { console.log(err); } });
Now you know how to use Cloudinary with your express application.