Uploading Files Using Multer Middleware

Photo by Sigmund on Unsplash

Uploading Files Using Multer Middleware

Introduction

In this article we will be learning how to create a RESTFUL API endpoint to enable us upload a file to the backend/ server.

What is Multer

From the documentation, multer is defined as a node.js middleware whose primary purpose is for uploading files to the backend. This middleware as any other middleware helps to observe any incoming request and helps us manage any file attached to the request. When a requestis made from the frontend, we must ensure that Content-Type is set to multipart/form-data in the request headers when using RESTFUL API. This must be done for upload to be successful.

Let's get to business

Create your express server

This section involves setting up your server with express, if you're familiar with this process and would want to skip to using multer then you can skip this section. First, lets create a js file in a folder and name it app.js. Open your app.js file in your code editor and follow the steps below;

  1. Goto your terminal to initialize your npm for the project, type the following code;
npm init -y
  1. install the following dependencies for this project;
npm install express multer
npm install nodemon -D
  1. Add the following code to your app.js file;
// imports the express module into our project
const express = require('express')

// imports the multer module into our project
const multer = require('multer')

// creates an instance of our app server
const app = express()

// set our server to listen on port 5000
app.listen(5000, ()=> console.log('server is running on port 5000'))
  1. Goto to your package.json file and add a script to enable nodemon restart the server automatically anytime a change is done.
  1. Finally on the terminal run this script,
npm start
// server is running on port 5000

Now our server is live and we can begin to code the api endpoints we want to handle.

Using Multer middleware

Multer accepts an options config with contains 3 important properties used to save, filter the type of file you want to accept and/or limit the size of file that can be uploaded to the server. The multer function returns a middleware object that can be passed into our endpoint. See code below;

const upload = multer();

multer returns a middleware object which we assign to upload variable. Now we should pass a config option to define how we want how our file to be handled. These important properties include;

  • storage/dist

  • limits

  • filefilter

Storage/dist

The storage/dist propety tells multer where to store the file. If you want more control over your uploads, you'll want to use the storage option instead of dest. Multer ships with storage engines DiskStorage and MemoryStorage. DiskStorage engine can help us to also customise how we want our file to be saved. Let's add storage to our multer;

const MIME_TYPE = {
    "image/png": "png",
    "image/jpg": "jpg",
    "image/jpeg": "jpeg",
};

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./images"); // Storage location
    },
    filename: function (req, file, cb) {
        cb(
            null,
            file.fieldname + "-" + Date.now() + "." + MIME_TYPE[file.mimetype]
        ); // return a unique file name for every file
    },
});
const upload = multer({storage:storage}).single('profile_img');

There are two options available, destination and filename. They are both functions that determine where the file should be stored. We will be storing our file in a folder callled images, make sure to create a folder in your root directory called images.

filename is a function used to create a customised filename before saving to our backend.

limits

This is used to set limits to the file size to accept. Here, we will be setting the limit to file size;

const upload = multer({
storage:storage
    limits: {
        fileSize: 1000000,
    }, // this set the maximum file that can be uploaded to 1mb
}).single('profile_img');

filefilter This sets to a function that is used to filter the type of files that should be accepted. This can help to protect against uploading random files and hackers who may want to upload a corrupt file to your server.

const MIME_TYPE = {
    "image/png": "png",
    "image/jpg": "jpg",
    "image/jpeg": "jpeg",
}; // store the different image formats we want to accept

const upload = multer({
storage:storage
    limits: {
        fileSize: 1000000,
    }, // this set the maximum file that can be uploaded to 1mb
    fileFilter: (req, file, cb) => {
        const uploadFile = !!MIME_TYPE[file.mimetype]; //check that this file type is acceptable
        if (!uploadFile) {
            return cb(new Error("Error with wrong file")); // return an error if file type is not acceptable
        }
        cb(null, true); // allow the file to saved if file type is acceptable
    }
}).single('profile_img');

Using the middleware object in our route

app.post("/upload", (req, res, next) => {
    console.log("upload was called");

    upload(req, res, (err) => {
    // check if there is an error trying to upload
   // return an error if error occurred 
   // else file upload was successful 
        if (err instanceof multer.MulterError) {
  // handle error that is associated with multer
       res.status(500).json({ message: err.message });
        } else if (err) {
 // handle any other form of error
            res.status(500).json({ message: err.message });
       } else {
// file upload was successful
// continue with other logic for this endpoint

            res.json({ message: "upload successful!" });
        }
    });
});

Finally

We have successfully, uploaded a file to the backend server. I hope learnt a lot. I will be happy to answer questions in the comments. Don't forget to like and share if you enjoyed and learnt something new from the post.

Resources

Multer

Express

Link to github file