Create and Deploy an Image API (Node.js/Express.js, MongoDB/Mongoose)

Noor AhmedNoor Ahmed
4 min read

Table of Contents:

  • Introduction

  • Folder Structure

  • Installations and Dependencies

  • Setup Node/Express Server

  • MongoDB/Mongoose Connection

  • Post Images

  • Search for Images

  • Deployment

Introduction

In this article, I will show how you can create an API that can upload, search and render images. This will be created using Node.js/Express.js, MongoDB/Mongoose and for deployment, we will use render.com. For the full source code here is my GitHub repository of the project: https://github.com/N00rAhmed/Image-API

Folder Structure

First, you will have to go to your terminal and type npm init -y. Once that is completed create a file called app.js, this is where all of the logic for our API will be for now and create another file called config.js here we will store the MongoDB URI. After doing this your folder structure should look similar to this:

Installations and Dependencies

Please install these packages in your terminal:

npm i express
npm i nodemon
npm i cors
npm i multer
npm i mongoose

Setup Node/Express Server

const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const bodyParser = require('body-parser');
const cors = require('cors');
const config = require('./config');

const app = express();
const port = 3000;

// Parse JSON bodies
app.use(bodyParser.json());

app.use(cors());

// Start the server
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

Here we have setup our server to run locally on port 3000: http://localhost:3000 . Also, we have initialized packages such as Cors which will help us avoid errors with security issues later on and we will be using the multer package for storing our images and mongoose will be used later on for sending our images to a MongoDB database. You can run this file you can type nodemon app.js in the terminal and you will see a message saying Server is running on port 3000 :

MongoDB/Mongoose Connection

Go to the MongoDB Atlas website and create a cluster. For a detailed explanation of how to do this please refer to this tutorial:

Once you have created your cluster go to your config.js file and add your MongoDB URI with the username and password:

// config.js
module.exports = {
    mongoURI: 'URI GOES HERE',
  };

Now in app.js add this code:

// Connect to MongoDB
mongoose.connect(config.mongoURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  });

const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));

// Create a schema for the image model
const imageSchema = new mongoose.Schema({
  name: String,
  data: Buffer,
  contentType: String,
});

// Create the image model
const Image = mongoose.model('Image', imageSchema);

In this code sample, we are connecting to our MongoDB database by mongoose.connect(config.mongoURI which accesses our URI from the config.js file.

The imageSchema is where the information of the image file will be stored. Inside the schema, there are three values which are the name, data and contentType. The name value stores the name of the image file as a string and the data value uses Buffer to store the image as binary data. The contentType value stores the content type of the image such as jpeg, png etc.

Post Images

// Configure multer for file upload
const storage = multer.memoryStorage();
const upload = multer({ storage });

// Define the API endpoint for image upload
app.post('/upload', upload.single('image'), async (req, res) => {
    if (!req.file) {
      return res.status(400).send('No file uploaded.');
    }

    const image = new Image();
    image.name = req.file.originalname;
    image.data = req.file.buffer;
    image.contentType = req.file.mimetype;

    try {
      await image.save();
      res.status(200).send('Image uploaded successfully.');
    } catch (err) {
      console.error(err);
      res.status(500).send('Failed to upload image.');
    }
  });

Here we are using the multer package for storing the image file when it gets uploaded from our POST request app.post('/upload', and then sent to our database. Here is an example of how you would test the API in Postman, the link being used is the deployed version of the API:

Search for Images

  app.get('/image/:id', async (req, res) => {
    const imageId = req.params.id;

    try {
      const image = await Image.findById(imageId);

      if (!image) {
        return res.status(404).send('Image not found.');
      }

      res.setHeader('Content-Type', image.contentType);
      res.send(image.data);
    } catch (err) {
      console.error(err);
      res.status(500).send('Failed to find image.');
    }
  });

The above will allow you to search for your images by typing the ID and pressing enter which will then render the image for you. The ID of your individual images can be found in your MongoDB database. We are using a GET request to get the image with the search params /image/:id. Also, we are using if statements to say if there isn't an existing image at that endpoint then return a 404 error.

Deployment

In order to deploy the Image API you must first upload your code to GitHub, once you have done that please go to render.com and create your account. Then select Web Service and choose your GitHub repository. Finally, fill in the details below and click Create Web Service which will deploy your API:

After it has deployed successfully you should see something like this:

Congrats you have successfully deployed your API 🥳

1
Subscribe to my newsletter

Read articles from Noor Ahmed directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Noor Ahmed
Noor Ahmed

I am a software engineer intern from the UK and I have worked with multiple technologies like MERN stack, JavaScript, Python etc. I also like to contribute to open source on Github.