Upload and Retrieve Image on MongoDB using Mongoose

To get started we need to install certain modules and NodeJs must be installed in the system.

Prerequisite: For getting started with this an individual is familiar with NodeJS, ExpressJS, MongoDB and Mongoose.

  • NodeJS: It is a free open source server environment that uses JavaScript on the server and runs on various platform (Windows, Linux, Unix, Mac OS X, etc.).It uses asynchronous programming.
  • ExpressJS: It is a NodeJS web application server framework, designed for building single-page, multi-page, and hybrid web applications. It is the de facto standard server framework for node.
  • MongoDB: MongoDB is a NoSQL database.MongoDB is a JSON document datastore. It allows you to store and query JSON style documents with a few smarts on top.
  • Mongoose: Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node. js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.

Before getting start install the required packages and modules.

  • Express allows us to set up middlewares to respond to HTTP Requests.
    npm install express --save
  • The module “body-parser” allows reading HTTP-POST data.
    npm install body-parser --save
  • Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
    npm install mongoose --save
  • Multer is a nodejs middleware used for uploading files.
    npm install multer --save
  • Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env.
    npm install dotenv --save
  • EJS or Embedded Javascript Templating is a templating engine used by Node.js. The template engine helps to create an HTML template with minimal code.
    npm install ejs --save

To upload an image and retrieve image by MongoDB using Mangoose lets begin, follow the each steps below one by one.

  • Step 1: To begin, we will create our server file ‘app.js’.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    var express = require('express')
    var app = express()
    var bodyParser = require('body-parser');
    var mongoose = require('mongoose')
      
    var fs = require('fs');
    var path = require('path');
    require('dotenv/config');

    chevron_right

    
    

  • Step 2: We will connect to the MongoDB using the URL at which database is found. Here ‘process.env.MONGO_URL’ is used in place of database url, it is because I have stored the url in ‘.env’ file which make it a environment variable and to load the url automatically we have used the module ‘dotenv’.Replace the ‘process.env.MONGO_URL’ with your database url.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Connecting to the database 
    mongoose.connect(process.env.MONGO_URL,
        { useNewUrlParser: true, useUnifiedTopology: true }, err => {
            console.log('connected')
        });

    chevron_right

    
    

  • Step 3: Once we have established a connection to our database and required all the necessary packages, we can now begin defining our server-side logic. So for storing an image in MongoDB, we need to create a schema with mongoose. For that create a model.js file and define the schema. The important point here is that our data type for the image is a Buffer, which allows us to store our image as data in the form of arrays.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    var mongoose = require('mongoose');
      
    var imageSchema = new mongoose.Schema({
        name: String,
        desc: String,
        img:
        {
            data: Buffer,
            contentType: String
        }
    });
      
    //Image is a model which has a schema imageSchema
      
    module.exports = new mongoose.model('Image', imageSchema);

    chevron_right

    
    

  • Step 4: We need to set EJS as our templating engine with Express which is a Node.js web application server framework, which is specifically designed for building single-page, multi-page, and hybrid web applications. It has become the standard server framework for node.js. The default behavior of EJS is that it looks into the ‘views’ folder for the templates to render. So, let’s make a ‘views’ folder in our main node project folder and make a file named “app.ejs” which is to be served on some desired request in our node project.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    app.use(bodyParser.urlencoded({ extended: false }))
    app.use(bodyParser.json())
      
    // Set EJS as templating engine 
    app.set("view engine", "ejs");

    chevron_right

    
    

  • Step 5: We must define the path of the image we are uploading. Here, we are using the middleware Multer to upload the photo on the server-side and also using module ‘path’ and ‘fs’ of node.js. Here, we use Multer to take a photo and put it in a folder called ‘uploads’ so we can easily access it later.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    var fs = require('fs');
    var path = require('path');
    var multer = require('multer');
      
    var storage = multer.diskStorage({
        destination: (req, file, cb) => {
            cb(null, 'uploads')
        },
        filename: (req, file, cb) => {
            cb(null, file.fieldname + '-' + Date.now())
        }
    });
      
    var upload = multer({ storage: storage });

    chevron_right

    
    

  • Step 6: Now, for using the Image model, first we need to load the model into app.js.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    var imgModel = require('./model');

    chevron_right

    
    

  • Step 7: Finally, we must handle our post and get requests to our database. Handling the GET request. This request is used to display all the data stored in the database.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Retriving the image
    app.get('/', (req, res) => {
        imgModel.find({}, (err, items) => {
            if (err) {
                console.log(err);
            }
            else {
                res.render('app', { items: items });
            }
        });
    });

    chevron_right

    
    

  • Ste 8: Handling the POST request. This request is used to handle the form data which is submitted by the user.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Uploading the image
    app.post('/', upload.single('image'), (req, res, next) => {
      
        var obj = {
            name: req.body.name,
            desc: req.body.desc,
            img: {
                data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
                contentType: 'image/png'
            }
        }
        imgModel.create(obj, (err, item) => {
            if (err) {
                console.log(err);
            }
            else {
                // item.save();
                res.redirect('/');
            }
        });
    });

    chevron_right

    
    

  • Step 9: Setting up the server at the port 3000. Here process.env.PORT is used for setting up the port dynamically at the time of deployment.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    app.listen('3000' || process.env.PORT, err => {
        if (err)
            throw err
        console.log('Server started')
    })

    chevron_right

    
    

Example: The final app.ejs Content. Here you can see that the url in src is different. It follows this format as the image is stored in binary format so we need to convert it into the base64 format which at the time of rendering converted into the image.

filter_none

edit
close

play_arrow

link
brightness_4
code

<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Uploading</title>
</head>
  
<body>
    <h1>To Upload Image on mongoDB</h1>
    <hr>
    <div>
        <form action="/" method="POST" enctype="multipart/form-data">
            <div>
                <label for="name">Image Title</label>
                <input type="text" id="name" placeholder="Name" 
                       value="" name="name" required>
            </div>
            <div>
                <label for="desc">Image Description</label>
                <textarea id="desc" name="pesc" value="" rows="2" 
                          placeholder="Description" required>
                </textarea>
            </div>
            <div>
                <label for="image">Upload Image</label>
                <input type="file" id="image" 
                       name="image" value="" required>
            </div>
            <div>
                <button type="submit">Submit</button>
            </div>
        </form>
    </div>
  
    <hr>
  
    <h1>Uplaoded Images</h1>
    <div>
        <% items.forEach(function(image) { %>
        <div>
            <div>
                <img src="data:image/<%=image.img.contentType%>;base64,
                     <%=image.img.data.toString('base64')%>">
                <div>
                    <h5><%= image.name %></h5>
                    <p><%= image.desc %></p>
                </div>
            </div>
        </div>
        <% }) %>
    </div>
</body>
  
</html>

chevron_right


Output Go to the browser and open localhost:3000/
Demo

full-stack-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.