DEV Community

Rajesh T
Rajesh T

Posted on

Storing images in MEAN stack application using "Cloudinary"

Saving images and videos of a web application is always challenging, because, performance of application matters.We have 2 options to deal with this

  1. Storing images in database

  2. Storing images in cloud

In this article ,i will explain how to store images and videos in "Cloudinary"

Cloudinary
Cloudinary is a cloud-based service that provides an end-to-end image and video management solution. The Node.js SDK provides simple, yet comprehensive image and video manipulation, optimization, and delivery capabilities that you can implement using code that integrates seamlessly with your existing Node.js SDK application.

The following diagrams explains the process of saving User data into database collection.

No alt text provided for this image
It contains 4 steps.

Step-1: Sending user data along with profile image to server by making HTTP POST request

Step-2: Image(or video i.e. a file) of request object can save to cloudinary storage.

Step-3 : Once the file is stored to cloudinary, it returns CDN link of the image

Step-4 : Add the CDN link of profile picture to user data and save it to Database(user collection)

Step-1-Sending user data along with profile image to server by making HTTP POST request
Create register component and register service in Angular application. Then, add registration form to register component.

register.component.html


<!--name-->

Name
class="form-control" ngModel>
  <!--username-->

 <div class="form-group">

 <label for="un">Username</label>

 <input type="text" id="un" name="username" class="form-control" ngModel>

 </div>


        <!--password-->

 <div class="form-group">

  <label for="pw">Password</label>

 <input type="text" id="pw" name="password" class="form-control" ngModel>

 </div>




          <!--email-->
<label for="em">Email</label>

<input type="email" id="em" name="email" class="form-control" ngModel>

<!--date of birth-->

 <label for="db">Email</label>

 <input type="date" id="db" name="dob" class="form-control" ngModel>

<!--profile image-->

Choose profile image

    <button type="submit" class="btn btn-success">Register</button>

register.component.ts

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { RegisterService } from '../register.service';
import { Router } from '@angular/router';

@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {

//inject register service obj
constructor(private rs:RegisterService,private router:Router) { }

ngOnInit(): void {
}

file: File;

imageUrl: string | ArrayBuffer ="https://bulma.io/images/placeholders/480x480.png";

fileName: string = "No file selected";

//this method receives file content ,read and make it ready for preview

onChange(file: File) {

if (file) {
  this.fileName = file.name;
  this.file = file;
Enter fullscreen mode Exit fullscreen mode

/*The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer,
using File or Blob objects to specify the file or data to read. */

  const reader = new FileReader();
Enter fullscreen mode Exit fullscreen mode

//The readAsDataURL method is used to read the contents of the specified Blob or File
reader.readAsDataURL(file);

/A handler for the load event. This event is triggered
each time the reading operation is successfully completed.
The FileReader.onload property contains an event handler
executed when the load event is fired
/

  reader.onload = () => {
    /*  the "result" attribute contains the data as a base64 encoded string.*/

    this.imageUrl = reader.result;

  };
}
Enter fullscreen mode Exit fullscreen mode

}

//this methid is called at form submission
submit(formObj:NgForm)
{
//formdata obj preperation
let formData=new FormData();

//get user object from NgForm object
let userObj=formObj.value;

  //append image to it
  formData.append("photo",this.file);

 //append user object by converting it into string
  formData.append("userObj",JSON.stringify(userObj));


 //pass "formData" object to register service to make HTTP POST request 
  this.rs.doRegister(formData).subscribe((result)=>{

      if( result["message"]=="user existed")
       {
         alert("user already existed");
         formObj.reset();
       }
     if( result["message"]=="user created")
       {
         alert("user created successfully");
         //redirect to login page
         this.router.navigate(['./login']);
       }
  })
Enter fullscreen mode Exit fullscreen mode

}

}

register.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class RegisterService {

constructor(private hc:HttpClient) { }

doRegister(userObj):Observable
{
//make http post req and returns Observable
return this.hc.post('/user/register',userObj);

}
}

Step-2: Image(or video i.e. a file) of request object can save to cloudinary storage.
Once the FormData object is reached to server.js, it will execute "userApi.js" by sending request object to it.

server.js

//load express function
const exp=require("express");
//create express obj
const app=exp();

const path=require("path");

//connecting ANgular app with this server
app.use(exp.static(path.join(__dirname,'./dist/AngApp9WithMultipleModules')));

//import MongoClient
const mc=require("mongodb").MongoClient;

//import user router

const userApiObj=require("./apis/userApi");

//if path contains '/user'
app.use('/user',userApiObj);
;

//middleware to handle unavailable paths
app.use((req,res,next)=>{
res.send({message:path ${req.url} is not available});
});

//get db url from mongo atlas
var dbUrl = "mongodb+srv://b26:b26@cluster0-z3col.mongodb.net/test?retryWrites=true&w=majority";

mc.connect(dbUrl,{useNewUrlParser:true,useUnifiedTopology:true},(err,client)=>{
if(err)
{
console.log("Err in db connect ",err);
}
else{
//get db connection object
let b26DatabaseObject=client.db("b26db");

    //get collection objects
    let userCollectionObj=b26DatabaseObject.collection("usercollection");
    let adminCollectionObj=b26DatabaseObject.collection("admincollection");


    console.log("db connected..");



    //assign collection objects to "locals" object of "app"
    app.locals.userCollectionObj=userCollectionObj;
    app.locals.adminCollectionObj=adminCollectionObj;



    const port=4000;
    app.listen(port,()=>{ console.log(`server listening on port ${port}`)});


}
Enter fullscreen mode Exit fullscreen mode

});

Now, we need to configure the cloudinary service.For that, register and login into https://cloudinary.com/.

Then it will provide crdentials to use its API and they are "Cloud name","API Key" and "API secret".

Now install and import the following modules at userApi.js

cloudinary

                                           multer-storage-cloudinary

                                           multer
Enter fullscreen mode Exit fullscreen mode

const cloudinary = require("cloudinary");

const cloudinaryStorage = require("multer-storage-cloudinary");

const multer = require("multer");

Now configure cloudinary with its credentials.

cloudinary.config({

cloud_name: "xxxxxxx",

api_key: "xxxxxx",

api_secret: "xxxxxxx",

});

Now, after configuring cloudinary, configure storage at cloudinary.

var storage = cloudinaryStorage({

cloudinary: cloudinary,

folder: "user-profiles",

allowedFormats: ["jpg", "png"],

filename: function (req, file, cb) {

 cb(undefined, file.fieldname + "-" + Date.now());
Enter fullscreen mode Exit fullscreen mode

},

});

Now,configure multer middleware

var upload = multer({ storage: storage });

Then it will use configured storage location at cloudinary to store file data

Step-3 : Once the file is stored to cloudinary, it returns CDN link of the image
Execute multer middleware before request handling middleware by adding it as second argumant like below.

the method "single(string)" will upload single image to storage location.

const exp = require("express");
const userRouter = exp.Router();

//use body parser middleware
userRouter.use(exp.json());

userRouter.post("/register", upload.single("photo"), (req, res, next) => {

console.log("req body is ",req.body)

/multer middleware will execute first before req handling middleware
save image to cloudinary and get CDN link in req.file.secure_url property
/

console.log("url is ", req.file.secure_url);
console.log("user data is ", JSON.parse(req.body.userObj));

//now parse userObj and assign to req.body

req.body=JSON.parse(req.body.userObj); 


//add CDN link of profile image to req.body


req.body.profileImageUrl= req.file.secure_url;
Enter fullscreen mode Exit fullscreen mode

// write user create logic here..............................

}

Step-4 : Add the CDN link of profile picture to user data and save it to Database(user collection)
The following Code contains user registration logic

userRouter.post("/register", upload.single("photo"), (req, res, next) => {

console.log("req body is ",req.body)
console.log("url is ", req.file.secure_url);
console.log("user data is ", JSON.parse(req.body.userObj));

req.body=JSON.parse(req.body.userObj);

req.body.imgUrl = req.file.secure_url;

delete req.body.photo;

//get usercollection object from "req.app.locals" object
let userCollectionObj = req.app.locals.userCollectionObj;

//check for a user in user collection with the "username" received from client
userCollectionObj.findOne({ username: req.body.username }, (err, userObj) => {
if (err) {
next(err);
}

//if user is existed
if (userObj != null) {
  res.send({
    message: "user existed",
  });
}

//if user is not existed

else {
  //insert "req.body" into usercollection

  //hash the password
  bcrypt.hash(req.body.password, 7, (err, hashedPassword) => {
    if (err) {
      next(err);
    }


    //replace paint text password with hashedpassword
    req.body.password = hashedPassword;


    //insert req.body to user collection
    userCollectionObj.insertOne(req.body, (err, success) => {
      if (err) {
        next(err);
      }
      res.send({ message: "user created" });
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

});
});

Now the user collection of database contains user object will all user data along with CDN link of his profile image.

Top comments (0)