Handle a File Upload in Node.js and Express with Multer

OpenJavaScript 0

Last updated: January 10, 2023.

The Multer package for Node.js allows you to handle the uploading of a single or multiple files as well as additional form data.

We’ll use the following HTML form as an example, which contains a text input element and the opportunity for a user to upload one or more files:

<form>
    <input type="text" name="file-name" id="name">
    <input type="file" name="file" id="files" multiple>
    <button type="submit">Submit</button>
</form>

Sticking with the frontend, we’ll now handle the submission of the form with JavaScript:

const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
    
    e.preventDefault();
    // Prevents HTML handling submission
    const name = document.getElementById("name");
    const files = document.getElementById("files");
    const formData = new FormData();
    // Creates empty formData object
    formData.append("name", name.value);
    // Appends value of text input
    for(let i =0; i < files.files.length; i++) {
        formData.append("files", files.files[i]);
    }
    // Appends value(s) of file input
    // Post data to Node and Express server:
    fetch('http://127.0.0.1:5000/api', {
        method: 'POST',
        body: formData, // Payload is formData object
    })
    .then(res => res.json())
    .then(data => console.log(data));
})

Now, on the backend, we’ll handle the request using a Node and Express server.

For our server, we’ll be relying on the express, multer and cors libraries. So make sure to install these when setting up a new project in your chosen directory first:

npm init --y
npm i express multer cors

Multer works by intercepting an incoming request to the server.

To begin, you’ll want to specify a destination property and a filename property as values on multer.diskStorage(), to set where the file will be saved and what name it will be saved under, respectively.

Then, set this as the value of the storage property when calling multer.

Finally, include this as the middleware on the incoming request path, making sure that the the string passing in to upload.array() matches the reference given to the files when constructing the formData object on the frontend:

const express = require("express");
const multer = require('multer');
const cors = require('cors');

var app = express();
app.use(cors()); // Allows incoming requests from any IP

// Start by creating some disk storage options:
const storage = multer.diskStorage({
    destination: function (req, file, callback) {
        callback(null, __dirname + '/uploads');
    },
    // Sets file(s) to be saved in uploads folder in same directory
    filename: function (req, file, callback) {
        callback(null, file.originalname);
    }
    // Sets saved filename(s) to be original filename(s)
  })
  
// Set saved storage options:
const upload = multer({ storage: storage })

app.post("/api", upload.array("files"), (req, res) => {
// Sets multer to intercept files named "files" on uploaded form data

    console.log(req.body); // Logs form body values
    console.log(req.files); // Logs any files
    res.json({ message: "File(s) uploaded successfully" });

});

app.listen(5000, function(){
    console.log("Server running on port 5000");
});

After submitting the form, output in the console should look something like this:

Console output after uploading files with Multer.

Happy uploading!

Related links