Upload multiple images in Node JS and Mongo DB

In this article, we are going to teach you, how you can upload multiple images in Node JS and Mongo DB.

Video tutorial:

Initializing the project

First, you need to create an empty folder and open a command prompt or terminal in it. Then run the following command in that CMD:

> npm init

It will ask multiple questions, just press enter to set the default values.

Then you need to install the express and HTTP modules. So run the following command:

> npm install express http

Then create a file named server.js and write the following code in it:

const express = require("express")
const app = express()
const http = require("http").createServer(app)

// [include Mongo DB]

// [set view engine]

// [Express formidable and FS module]

// [recursive function to upload images]

const port = process.env.PORT || 3000
http.listen(port, function () {
    console.log("Server started running at port: " + port)

    // [connect Mongo DB]
})

If you open your CMD, you will see the message “Server started running at port: 3000”.

You can check your project from the URL: http://localhost:3000/

Installing Mongo DB

To install the Mongo DB module, first, run the following command in your terminal:

> npm install mongodb

Then include the Mongo DB module in your server.js file in the [include Mongo DB] section:

const mongoClient = require("mongodb").MongoClient

Then connect with the database by writing the following code in the [connect Mongo DB] section:

mongoClient.connect("mongodb://localhost:27017", async function (error, client) {
    if (error) {
        console.error(error)
        return
    }

    const db = client.db("multiple_images_upload")
    console.log("Database connected")

    // [routes]
})

To learn more about Mongo DB, check our tutorials on Mongo DB here.

Display form to upload multiple images

To display an HTML file in Node JS, we need to install a module named EJS. You can install it by running the following command:

> npm install ejs

Then we need to tell our app to use the EJS as the templating engine. So write the following code in the [set view engine] section:

app.set("view engine", "ejs")

Then create a GET route in the [routes] section of server.js file:

app.get("/", async function (request, result) {
    result.render("home")
})

Then create a folder named views and inside this folder create a new file named home.ejs. In this file, we will create a form with an input type file.

<!-- home.ejs -->

<form onsubmit="uploadImages()" enctype="multipart/form-data">
    <input type="file" multiple accept="image/*" name="images" required />

    <input type="submit" value="Upload images" />
</form>

multiple: This will allow multiple file uploads.

accept=”image/*”: This allows only image files to be uploaded.

Then we will create this Javascript function to call an AJAX.

<script>
    function uploadImages() {
        // prevent the form from reloading the page
        event.preventDefault()

        // get form tag
        const form = event.target

        // create form data object from <form>
        const formData = new FormData(form)

        // create AJAX object
        const ajax = new XMLHttpRequest()

        // 1st parameter = method, GET/POST
        // 2nd parameter = path to server file
        // 3rd parameter = asynchronous
        ajax.open("POST", "/uploadImages", true)

        // when status of request changes
        ajax.onreadystatechange = function () {
            // operation is completed
            if (this.readyState == 4) {
                // response from server is okay
                if (this.status == 200) {
                    // response from server
                    console.log(this.responseText)
                }
            }
        }

        // send AJAX request
        ajax.send(formData)
    }
</script>

Comments have been added with each line for the explanation.

Upload multiple images in Node JS

To handle the form data object, we must first install the express-formidable and fs modules. FS stands for File System. To install these modules, run the following command:

> npm install express-formidable fs

Then you need to include these modules in your server.js file, in the [Express formidable and FS module] section:

const formidable = require("express-formidable")
app.use(formidable({
    multiples: true, // request.files to be arrays of files
}))

const fileSystem = require("fs")
app.use("/uploads", express.static(__dirname + "/uploads"))

Then create a folder named uploads at the root of your project.

After that, create the following POST route to handle that AJAX request:

app.post("/uploadImages", async function (request, result) {
    const images = []
    if (Array.isArray(request.files.images)) {
        for (let a = 0; a < request.files.images.length; a++) {
            images.push(request.files.images[a])
        }
    } else {
        images.push(request.files.images)
    }

    callbackFileUpload(images, 0, [], async function (savedPaths) {
        await db.collection("images").insertOne({
            images: savedPaths
        })

        result.send("Images has been uploaded.")
    })
})

To upload images, we will be using a recursive function. So create a recursive function in the [recursive function to upload images] section:

function callbackFileUpload(images, index, savedPaths = [], success = null) {
	const self = this

	if (images.length > index) {

		fileSystem.readFile(images[index].path, function (error, data) {
			if (error) {
				console.error(error)
				return
			}

			const filePath = "uploads/" + new Date().getTime() + "-" + images[index].name
			
			fileSystem.writeFile(filePath, data, async function (error) {
				if (error) {
					console.error(error)
					return
				}

				savedPaths.push(filePath)

				if (index == (images.length - 1)) {
					success(savedPaths)
				} else {
					index++
					callbackFileUpload(images, index, savedPaths, success)
				}
			})

			fileSystem.unlink(images[index].path, function (error) {
				if (error) {
					console.error(error)
					return
				}
			})
		})
	} else {
		success(savedPaths)
	}
}

Run the project now and you see a form with an input file and a submit button. Select multiple images from your computer and hit submit. Once submitted, you will see your uploaded images in the “uploads” folder and a new document will be created in the Mongo DB images collection.

Show uploaded images

Now we need to show all uploaded images. First, change your home route in server.js to the following:

app.get("/", async function (request, result) {
    const images = await db.collection("images").find({}).toArray()
    result.render("home", {
        images: images.length > 0 ? images[0].images : []
    })
})

This will pass all the images from the first document of images collection to the home file. Now go to your home.ejs and write the following for loop to display all images:

<%for (let a = 0; a < images.length; a++) { %>
    <img src="<%= images[a] %>" style="width: 100%;" />
<% } %>

Refresh the page now and you will be able to view all uploaded images.

If you face any problem in this, please do not hesitate to get in touch with me.

To run the following downloaded files, run the following command in your terminal first:

> npm update

[wpdm_package id=’1727′]

Leave a Reply

Your email address will not be published. Required fields are marked *