How to Upload a File to a Nodejs Server Using Multer
Published: 2023-05-01 13:20:33

## Introduction
File upload is a common feature in many web applications. This feature allows users to share documents, photos, videos, and other types of files.

Multer is a Nodejs middleware package that provides a simple and flexible way to handle file uploads allowing you to customize the file storage location, validate uploaded files, and much more.

In this tutorial, I will demo how to use Multer to handle file uploads in a NodeJS application.

## Prerequisite
To follow along with this tutorial, you should have the following:

- NodeJs installed on your device.

- A basic understanding of NodeJs and Express

## What is Multer?
Multer is a Nodejs middleware package for handling `multipart/form-data`. It is similar to `body-parser` which is also a middleware used to parse incoming HTTP requests in the request body and extract data in the form of JSON or URL-encoded data.

Although `body-parser` can technically parse the file upload data in the request body if it is sent as base64-encoded data, it is not efficient for handling large files. Multer is primarily designed for this and can handle large files more efficiently than sending them in the request body.

## Project Set Up
Create a project folder and navigate into it via your terminal.

```
mkdir fileUpload && cd fileUpload
```
Initialize the project by running:

```npm init -y```
This will generate a `package.json` file that will contain metadata about the project and the dependencies you will install.

![A package.json file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sz3mvnaoej00stmlmzfs.png)

Install the required packages. For this demo, you would need Express, Multer, and Postman.

[Express](https://expressjs.com/) - Is an unopinionated web framework for Nodejs used for creating HTTP web servers. Express provides an easy-to-use abstracted API built on Nodejs for interacting with the web server.

[Multer](https://www.npmjs.com/package/multer) - Is a Nodejs middleware package designed specifically to handle file uploads.

[Postman](https://www.postman.com/) - Is a software application used to test API endpoints.
```
npm i express multer
```
Create the entry file, `index.js` and open the project folder in your preferred text editor. For this tutorial, I'm using VScode.
```
touch index.js && code .
```

`code .` _opens up the project folder in vs code_.

In the `index.js` file, initialize an express app, and set up a simple Nodejs server that the browser would communicate with.
```
//import packages
const express = require("express");

//create express app
const app = express();

app.get('/', (req, res) => {
    res.send('File uploads with Nodejs')
})

//configure port for server
app.listen("3004", () => {
  console.log("server is running on port 3004");
});
```
## How does Multer process file upload behind the scenes?
Multer is a middleware for handling file uploads in Nodejs. Behind the scenes, Multer uses the "multipart/form-data" encoding for file uploads which is the standard format for HTML forms that include file inputs.

When a client sends a POST request with a "multipart/form-data" content-type and a file input, Multer intercepts the request before it reaches the route handler and begins parsing the form data. It uses the _busyboy_ library - a streaming parser that can handle large files without consuming too much memory - for parsing the form data. As the form data is being parsed, Multer extracts the file data and stores it in memory or on disk, depending on you set up the configuration. Also, Multer adds a `files` property on the request object which contains an array of objects representing the uploaded files.

_Note, for single file upload, it adds `file` property._

Once Multer has finished parsing the form data and storing the files, it calls the next middleware in the stack allowing the route handler to access the uploaded files through the files property on the request object.

## Configuring Multer in the Server
Multer comes shipped with a number of configuration options such as setting the file size limits, defining the file naming conventions, filtering the type of files to be uploaded, and specifying a destination directory for storing the uploaded files. These options can be used to customize Multer's behavior to fit the specific need of your application.

Here's an example of how you can configure Multer in your Express server to accept files from the client.

Import the Multer package in the `index.js` file and add the following code.
```
const multer = require('multer');
//require path module
const path = require('path')

//configure storage 
const storage = multer.diskStorage({
    destination: function(req, file, cb){
        cb(null, './public/images')
    },
    filename: function(req, file, cb){
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
        cb(null, uniqueSuffix + path.extname(file.originalname))
    }
})

//create middleware
const upload = multer({storage: storage})
```
Note: You should first create the directory where you want to upload the files to. This is what you specify in the destination option. For this demo, I created an images folder in the public directory.

Next, create a route handler for the file upload.
```
app.post("/", upload.single('image'), (req, res) => {
    console.log(req.file)
  res.send("File uploaded successfully");
});
```
In this route handler, the upload middleware is called and passed the name of the field in the form which the file is uploaded from - in this case,image .

Multer also lets you upload multiple files using `upload.array()` .

Open Postman to test the implementation so far.


![Screenshot of result in postman](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nt90qnemivhufxtrvjz2.png)

At this point, you should see the uploaded file in the destination folder you specified.

Alternatively, if you want to test this using an HTML form on the frontend, you should include the enctype attribute in the form and set its value to multipart/form-data like this:
```
 <form method="POST" action="/" enctype="multipart/form-data">
        <input type="file" name="image">
        <input type="submit">
    </form>
```
## How to Validate Uploaded Files
Multer has a built-in `fileFilter` method which can be used to validate the uploaded files. With this method, you can define conditions that will run specific checks on the file. For example, say you only want jpeg, jpg or png file types to be uploaded. You can configure a file filter option like this:
```
const filterOption = (req, file, cb) => {
     if (file.mimetype == 'image/jpeg' || file.mimetype == 'image/png' || file.mimetype == 'image/jpg') {
        cb(null, true);
    } else {
        cb(null, false);
    }
}
```
This function checks the `mimetype` property of the `file` object to determine whether the uploaded file is an image of type jpeg, png, or jpg. If the file is one of these types, the function calls the `cb` callback with the first argument null and the second argument as `true` which means that the file should be accepted and passed on to the next middleware or route handler.

However, If the file is not one of the accepted types, the function calls the `cb` callback with the first argument `null` and the second argument as `false` which means that the file should be rejected and an error message should be sent to the user.

To include this option in the previous Multer configuration, edit the `upload` middleware function to look this way:
```
const upload = multer({storage: storage, fileFilter: filterOption})
```
The final code should look like this:
```
const express = require("express");
const multer = require("multer");
const path = require('path')
const app = express();
app.use(express.static("public"));
const storage = multer.diskStorage({
    destination: function(req, file, cb){
        cb(null, './public/images')
    },
    filename: function(req, file, cb){
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
        cb(null, uniqueSuffix + path.extname(file.originalname))
    }
})

const upload = multer({storage: storage, fileFilter: filterOption})

app.get('/', (req, res) => {
  res.send('File uploads with Nodejs')
});

app.post("/", upload.single('image'), (req, res) => {
    console.log(req.file)
  res.status(200).json({status: 'success', message: "Upload successful!"});
});

app.listen("3004", () => {
  console.log("server is running on port 3004");
});
```
## Conclusion
In this tutorial, you have learned the basics of file uploading in Nodejs including how to set up and configure Multer to handle file uploads. You also learned how to customize the uploading process based on your specific needs. By following the steps outlined in this post, you can quickly and easily integrate Multer into your Nodejs application.

Thank you for reading!

Happy coding :)