How To Upload Multiple Image with Multer In NodeJS & ExpressJS

5 min read
Multer in Nodejs

In modern web applications, it’s common to have a feature for users to upload images. In this article, we will cover how to upload an image in Node & Express application using Multer, a middleware for handling file uploads.

After building backend side application, we will show you how to integrate the backend code with frontend tools, react and vue. So you can skip the part of article you don’t need. Let’s get started with nodejs part.

Set Up Backend

We will first start with setting up the backend. First, create a new directory for your project and initialize a new Node.js project:

mkdir my-project
cd my-project
npm init -y 

Install The Packages

Next, install the required packages using npm:

npm install express multer

CREATE A SERVER

Once the packages have been imported into our application, we can use expressjs to create a basic server.

const express = require('express');
const app = express();

// Codes Here

app.listen(3001, () => {
  console.log('Server listening on port 3001');
});

The server is configured to operate on PORT 3001 and can receive requests for image uploads.

SET UP MULTER

To enable file uploads on the server, we need to configure the Multer middleware. This involves defining several options, such as the maximum file size, the file types that are allowed, and the location where uploaded files should be stored :

const multer = require("multer");

const TARGET = "public/uploads/";
const MAX_FILE = 2;
const MAX_FILE_SIZE = 2 * 1024 * 1024; // 2 MB

function destination(req, file, cb) {
  cb(null, TARGET);
}

function filename(req, file, cb) {
  cb(null, file.fieldname + "-" + Date.now() + "." + file.originalname.split(".").pop());
}

const storage = multer.diskStorage({
  destination,
  filename,
});
  • TARGET is the path to the directory where uploaded files will be stored. In this case, it is set to “public/uploads/”.
  • MAX_FILE is the maximum number of files that can be uploaded in a single request. It is set to 2.
  • MAX_FILE_SIZE is the maximum size (in bytes) of an uploaded file. It is set to 2 * 1024 * 1024, which is equivalent to 2 megabytes.
  • The destination function determines the destination or target for the uploaded files.
  • Filename function sets the filename for the uploaded file by calling the callback function. The filename string consists of the original fieldname, a timestamp, and the file extension.
  • Finally, the multer.diskStorage() method creates a disk storage engine for storing uploaded files

SET LIMITS FOR IMAGES

The following code defines a fileFilter function that is used as an option for the multer() middleware. The purpose of the fileFilter function is to determine which files should be accepted and uploaded by the middleware.

function fileFilter(req, file, cb) {
  if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") cb(null, true);
  else cb(null, false);
}

This fileFilter function ensures that only image files with a jpeg or png extension are accepted and uploaded by the multer() middleware. If any other file types are uploaded, they will be rejected.

CREATE MULTER MIDDLEWARE

The following code initializes the multer middleware with the specified options and creates a upload object that can be used to handle file uploads.

The multer() function takes an options object as its argument. In this case, the options object has the following properties:

  • storage: Specifies the storage engine that will be used to store uploaded files. It is set to the storage engine that was created earlier using the multer.diskStorage() method.
  • fileFilter: Specifies the file filter function that will be used to determine which files should be accepted and uploaded. It is set to the fileFilter function that was defined earlier.
  • limits: Specifies an object that contains limits on the size and number of files that can be uploaded. In this case, it is set to an object with two properties:
  • files: The maximum number of files that can be uploaded in a single request. It is set to MAX_FILE, which is defined earlier as 2.
  • fileSize: The maximum size (in bytes) of an uploaded file. It is set to MAX_FILE_SIZE, which is defined earlier as 2 * 1024 * 1024 (i.e., 2 megabytes).
const upload = multer({
  storage: storage,
  fileFilter: fileFilter,
  limits: {
    files: MAX_FILE,
    fileSize: MAX_FILE_SIZE,
  },
});

Create An Endpoint To Handle Uploading Images

This code creates a route or endpoint using app.post() method to handle file uploads.

The upload.array(“images”, MAX_FILE) middleware handles the file upload, where “images” is the name of the field that contains the uploaded files, and MAX_FILE is the maximum number of files that can be uploaded at once.

// Create a route that uses the upload function to handle the file upload
app.post("/upload", upload.array("images", MAX_FILE), (req, res) => {
  try {
    const numFiles = req.files?.length;
    if (numFiles > 0) {
      return res.send(`Uploaded ${numFiles} image(s) successfully!`);
    }
    res.status(400).send("No files uploaded!");
  } catch (err) {
    if (err instanceof multer.MulterError) res.status(400).send(err.message);
    else res.status(500).send(err.message);
  }
});

The function checks if any files were uploaded using the req.files?.length property If at least one file was uploaded, it sends a success message to the client. Otherwise, it returns an error message.

Integrate The Multer With Frontend

Now, we will walk you through the process of integrating the backend for uploading images with two popular frontend frameworks, React and Vue.

Integrate Multer With React

For achiving file uploads in a reactjs application, you would need to create a form in your React app that allows the user to select a file to upload. Here is an example of how you can do this:

import React, { useState } from "react";

function App() {
  const [file, setFile] = useState(null);

  const handleFileUpload = (event) => {
    setFile(event.target.files[0]);
  };

  const handleSubmit = async (event) => {
    event.preventDefault();
    const formData = new FormData();
    formData.append("images", file);
    try {
      const response = await fetch("http://localhost:3001/upload", {
        method: "POST",
        body: formData,
      });
      const data = await response.text();
      console.log(data);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="file" onChange={handleFileUpload} />
        <button type="submit">Upload</button>
      </form>
    </div>
  );
}

export default App;

In this example, we use the useState hook to manage the selected file. When the user selects a file using the file input field, the handleFileUpload function is called to set the file state.

When the user submits the form, we create a new FormData object and append the selected file to it. We then send a POST request to the server using the fetch() API, passing the FormData object as the body of the request.

When the server responds, we log the response to the console.

Integrate Multer With VueJS

To integrate this code with Vue.js, you can create a form in a Vue component that allows users to select and upload files, and use the Fetch API to make a POST request to the /upload endpoint of the Express server. Here’s an example implementation:

<template>
  <form @submit.prevent="uploadFiles">
    <input type="file" name="images" multiple />
    <button type="submit">Upload Files</button>
  </form>
</template>

<script>
export default {
  methods: {
    async uploadFiles() {
      const files = document.querySelector('input[type=file]').files;
      const formData = new FormData();
      for (let i = 0; i < files.length; i++) {
        formData.append('images', files[i]);
      }
      try {
        const response = await fetch('/upload', {
          method: 'POST',
          body: formData,
        });
        if (!response.ok) {
          throw new Error('Upload failed');
        }
        const message = await response.text();
        console.log(message);
      } catch (error) {
        console.error(error.message);
      }
    },
  },
};
</script>

The process remains the same as in ReactJS, where you create a form to handle file uploads and send the uploaded files to the server.

Conclusion

This comprehensive article covers the process of uploading multiple images in a Node.js and Express application using the Multer middleware with configuration for target directory and limits. Additionally, we demonstrate how to integrate the backend with popular frontend tools such as React and Vue.js.

Thank you for reading.

Leave a Reply

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