DEV Community

loading...
Cover image for How To Upload Files With Multer Node.js and Express

How To Upload Files With Multer Node.js and Express

Joel Ndoh
I am a web developer, I create post around new things I learn every day from coding with javscript.
Updated on ・8 min read

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 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

USER@User MINGW64 ~/Desktop/upload
$ npm init -y
Enter fullscreen mode Exit fullscreen mode

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

npm install multer express
Enter fullscreen mode Exit fullscreen mode

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

// 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}`)
})
Enter fullscreen mode Exit fullscreen mode

Run the server code from the terminal

// Run the server form the terminal
$ node app.js
// Server is running on port 3000
Enter fullscreen mode Exit fullscreen mode

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

Alt Text

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.

<!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>
Enter fullscreen mode Exit fullscreen mode

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

app.use(express.static("public"))
// Server will render the html file in the public folder which is index.html
Enter fullscreen mode Exit fullscreen mode

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

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

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

Enter fullscreen mode Exit fullscreen mode

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

Alt Text
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"

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")
Enter fullscreen mode Exit fullscreen mode

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.

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
            }
    })
})
Enter fullscreen mode Exit fullscreen mode

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"

// 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}`)
})
Enter fullscreen mode Exit fullscreen mode

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 🤗🤗.

Discussion (4)

Collapse
dory profile image
dory

Thanks. I wonder if Multer process request that is sent without a form?

Collapse
ndohjapan profile image
Joel Ndoh Author

Hello Dory,

I don't think it is possible but if you find anyway of doing such I would be glad to hear it 🤗🤗

Collapse
promise_sheggsmann profile image
Promise Sheggsmann

Thanks soo much man!, this was life saving, made the post immediately I needed it.
I love the way you explain things, keep it up...

Collapse
ndohjapan profile image
Joel Ndoh Author

I am glad you liked it 😊😊😊.