How To Upload Files With Multer Node.js and Express
Tags: node, express, multer, tutorial
Published: 2021-05-17 09:09:55


Handling file input from client in the server is a very important part of both web and software development. Ranging from handling profile images of your users to handling pdf documents containing any important info about your users.

For long, anytime a project got to the stage of receiving files from the client side, I saw it as strange. 

I tried avoiding it but I found out it was something I could not just run away from as a web developer.

In the post I showed everything you must know about file upload  in Node.js.

By the end of this post you should know how to upload files from the client side, receive it properly and work with the file in your Node.js server. Won't that be great 🤗🤗

## Steps To Uploading Files 
1. Create your Node.js project folder
2. Install necessary modules
3. Create a simple Node.js server with Express
4. Create Html file which client will use in uploading files
5. Serve Html file from the Node.js server to the client
6. Create Route for receiving the files
7. Create location for storing files in server and setting restrictions to these files using multer
8. Pass the received file to Multer from the route created in step 6 

Each step will is explained below

I will be writing the codes in snippets and at the end of the post you will see the whole code in one place 😎😎. 

### Prerequisites
1. It is expected that you have node installed on your computer and it is up and running else  [click here](https://www.guru99.com/download-install-node-js.html) and when you are done you can continue with the post.

2. You should have had basic knowledge of express. How to create a route for any request method (GET, POST, PUT, DELETE)

If you met the above requirements, let's jump right in and rock 🥳🥳.

### 1. Creating Your Node.js Project Folder
> ⚠ Before we start, I want you know that every file are made up of bytes and its only the extension name that determines how the computer reads these files.

So create a folder and name it "upload"

Go to the directory of the folder in you terminal and type the following command in order to create a node project

```jsx
USER@User MINGW64 ~/Desktop/upload
$ npm init -y
```

This will create a node.js project with a file "package.json" in the folder

### 2. Installing Necessary Modules
We will use Node Package Manager (npm) to install the 2 modules we will be using for the simple project.

- multer
- express

In your command line, install the above modules

```jsx
npm install multer express
```

This will add the modules to the node modules folder in your project directory.

### 3. Creating Simple Node.js Server with Express
Create a file in the directory with name as "app.js"

In the file type or paste the below code into it

```jsx
// Include the express module into the poject for creating the server
const express = require("express")

// Include the multer module into the project for accepting files
const multer = require("multer")

// Include the path module (It is built-in and so need to install)
const path = require("path")
// Path module will be used to get extension name of every file entering the server

// We will set the object received from the express() function to a variable "app"
const app = express()

// Set a port on which the server will run on
const port = 3000

// Create the server and let it run on the port 3000
app.listen(port, () => {
	console.log(`Server is running on port ${port}`)
})
```

Run the server code from the terminal

```jsx
// Run the server form the terminal
$ node app.js
// Server is running on port 3000
```

From your browser,  make a request to the server using localhost:3000. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxfzokdr3wmmui6zzrba.jpg)

This means that our server is up and running but do not have any route to receive any request I make to the server.

### 4. Create Simple HTML for sending files to the server
The next thing to do, will be to create an HTML file through which users can send files to your Node.js server.

In the same directory, create a folder named "public" and in the folder create a file named "index.html"

Paste the HTML text below into the file.

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <title>File Upload</title>
</head>
<body>
    <div class="container">
        <h1>File Upload</h1>

<!--Create a form to send the file to a route  "upload"-->
<!--Set the request method to POST-->
<!--Set the encytype to "multipart/form-data" in order to send files and not just text-->
        <form action="/upload" method="POST" enctype="multipart/form-data">
            <div class="file-field input-field">
              <div class="btn grey">
                <input type="file" name="myImage">
              </div>
            </div>

            <button class="btn" type="submit">Submit</button>

          </form>
    </div>
</body>

</html>
```

After creating the file, the next question should be "How will you show the users this HTML file for them to insert their files?" 🤷‍♂️🤷‍♂️.

### 5. Serve the HTML file From The Server Once A Request Is Made
At the top of  your code in "app.js", insert the code below

```jsx
app.use(express.static("public"))
// Server will render the html file in the public folder which is index.html
```

The above line of code will tell express to serve anything to the client from the "public" folder

In your terminal restart the app by press "Ctrl+C"  for windows and "Cmd+C" on Mac and typing in `node app.js`

Now make a request from your browser

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txhbg1wl82gslddxaodb.jpg)

You should see the html file rendered 🥳🥳

### 6. Create Route For Receiving Files From The User
Now that the user can upload files from the browser, we will have to create a route to recieve these files in the server.

In your `app.js` , add the `POST` route to receive the file

```jsx
app.post("/upload", (req, res) => {
	// This is the response sent to the user in the browser once the file recieved
	res.send("Hello World")
})

```

If you send a file from the browser to the server, you will see a response of "Hello World"

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z74iygfzzzccvsnxqv48.gif)
And now that the user is getting a response, the next thing to do will be to handle these files in our server.

We will stores the files and even validate them 😎😎.
### 7. Create Location For Storing These Files With Multer
Here I will show you how to set restrictions to the type of file coming into your server . 

I guess as developer, you wouldn't want to receive pdfs into your server when you need images or would you ? 🤷‍♂️🤷‍♂️.

However, with the multer object we will create a location for storing the files.

The multer object has 3 main options passed to it.

- `storage and dest`
- `fileFilter`
- `limits`

    ### Storage and dest
    They are used to set the storage location for the file in your server but `storage` gives you more options. e.g to reset the name of the file in the server. 

    while `dest` just sets the location for storing the file and nothing else. 

    In this I will be using `storage` .

    ### fileFilter
    This is used to control file type coming into the server.

    > ⚠ Never trust file input from clients and so you must always validate the type of file to avoid people injecting codes into your server.

    ### limits
    It is used to set limit to either number of files, file size or any other property of files coming into the server

Read through the lines of code and paste at the top section of your code in "app.js"

```jsx
const upload = multer({
	storage: multer.diskStorage({
		destination: "/upload/images",  // Storage location
		filename: (req, res, (cb) => {
			cb(null, Date.now() + path.extname(file.originalname)) // return a unique file name for every file				
		})
	}),
	
	limits: {fileSize: 20000000},   // This limits file size to 2 million bytes(2mb)
		 
	fileFilter: (req, file, cb) => {
		const validFileTypes = /jpg|jpeg|png/ // Create regex to match jpg and png
		
		// Do the regex match to check if file extenxion match
		const extname = validFileTypes.test(path.extname(file.originalname).toLowerCase())
		
		if(extname === true){
			// Return true and file is saved
			 return cb(null, true)
		}else{
			// Return error message if file extension does not match
			return cb("Error: Images Only!")
			}
		}
}).single("myImage")
```
At the top of the code, I set the storage location to a folder "upload/images" which is in the public folder and I set the file size limit to 20000000 bytes (2mb).

And right at the bottom of the code I did a regex match (I will publish a post on regex very soon) to ensure that all files coming in had an extension of either "png", "jpg" or "jpeg".

Once all these are in place, the next we will do will be to pass these files into this variable "upload". "upload" is like an instance of multer class.

### 8. Pass the received file to Multer from the route created in step 6
At the route where the `POST`  request is made, add the `update` variable and pass users request into it.

```jsx
app.post("/upload", (req, res) => {
	// This is the response sent to the user in the browser once the file recieved
	upload(req, res, (err) => {
		if(err){
			res.send(err)
			// This will display the error message to the user
		}
		else{
			res.send("File Uploaded Successfully")
		// This shows the file has beem successfully uploaded
		// The image will be found in the public folder
			}
	})
})
```

With the above code when you send image files from the browser to the server, they are stored in the set location "upload/images" else the `err` message is displayed on the browser.

And finally we have come to the end 🥳🥳

Full code for "app.js"

```jsx
// Include the express module into the poject for creating the server
const express = require("express")

// Include the multer module into the project for accepting files
const multer = require("multer")

// Include the path module to extract file extension from every file entering the server.
const path = require("path")

// We will set the object received from the express() function to a variable "app"
const app = express()

// Set a port on which the server will run on
const port = 3000

const upload = multer({
	storage: multer.diskStorage({
				destination: "/upload/images",  // Storage location
				filename: (req, res, (cb) => {
						cb(null, Date.now() + path.extname(file.originalname))
						// return a unique file name for every file				
				})
		}),
	limits: {fileSize: 20000000},
	// This limits file size to 2 million bytes(2mb)	fileFilter: 
	fileFilter: (req, file, cb) => {
		// Create regex to match jpg and png
		const validFileTypes = /jpg|jpeg|png/
		
		// Do the regex match to check if file extenxion match
		const extname = fileTypes.test(path.extname(file.originalname).toLowerCase())
			if(mimetype && extname){
				// Return true and file is saved
        return cb(null, true)
    }else{
				// Return error message if file extension does not match
       return cb("Error: Images Only!")
    }
	}
}).single("myImage")

app.post("/upload", (req, res) => {
	// This is the response sent to the user in the browser once the file recieved
	upload(req, res, (err) => {
		if(err){
			res.send(err)
			// This will display the error message to the user
		}
		else{
			res.send("File Uploaded Successfully")
		// This shows the file has beem successfully uploaded
		// The image will be found in the public folder
			}
	})
})

// Create the server and let it run on the port 3001
app.listen(port, () => {
	console.log(`Server is running on port ${port}`)
})
```

Well, that's it! I have certainly learnt a lot from writing this down. I will be happy to answer questions in the comments 🤗🤗. 

My next post will be how we can store these files into our database (MongoDB) instead of our server system to avoid over loading it. 

Don't forget to like and share if you enjoyed and learnt something new from the post 🤗🤗.