ExpressJS - How to use express-fileupload to handle uploading files

The express-fileupload library is a middleware for Express framework that provides you with an easy way to handle file upload using the Express framework.

This tutorial will help you learn how to code an Express server that handles file upload using express-fileupload library.

Handling a file upload with express-fileupload

First, you need to have both express and express-fileupload modules installed in your project.

npm install express express-fileupload

Once you installed the modules, create a new file named app.js that will contain your Express server code.

Your express server will have two minimum routes:

  • The index / route (or default route) that renders an HTML file containing a <form>
  • The /upload route that will process file upload from its request

First, import the required modules for your server as follows:

const express = require("express");
const fileUpload = require("express-fileupload");
const path = require("path");

The path module will be used to create a valid absolute path for saving the uploaded file later.

For now, create a new express instance by calling the express() function:

const app = express();

Then, enable the express-fileupload middleware by calling app.use() method:

app.use(
  fileUpload()
);

Create the index / route that will serve an index.html file as follows:

app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "index.html"));
});

Now you need to create an index.html that will be rendered by Express when the browser sends a request to the index / route.

The HTML file contains a <form> element where you can upload a single file:

<!DOCTYPE html>
<html>
  <head>
    <title>Express File Upload</title>
  </head>
  <body>
    <h1>Express File Upload</h1>
    <form method="POST" action="/upload" enctype="multipart/form-data">
      <input type="file" name="myFile" />
      <input type="submit" />
    </form>
  </body>
</html>

The <form> element action attribute will contain the Express route for receiving uploads, while the enctype attribute is set to multipart/form-data.

The enctype stands for encoding type, and the multipart/form-data type allows you to send files through an HTTP POST request.

Also, take note of the input name attribute because you need it to retrieve the uploaded file later. The name attribute for the file upload above is set to myFile.

Finally, create the /upload route that will handle file upload over a POST request as shown below:

app.post("/upload", (req, res) => {
  // TODO: process the file upload
});

First, you need to check if the file is included in the request by checking if the req.files object is defined or not.

When there’s no file uploaded, send a 400 response with "No files were uploaded." as the message:

app.post("/upload", (req, res) => {
  if (!req.files) {
    return res.status(400).send("No files were uploaded.");
  }
});

When there is at least one file uploaded, you can continue to process the file by using the properties and methods provided by express-fileupload.

Following the name attribute of the file input above, the file you uploaded will be assigned under req.files.myFile.

app.post("/upload", (req, res) => {
  if (!req.files) {
    return res.status(400).send("No files were uploaded.");
  }

  const file = req.files.myFile;
});

Once you retrieved the file, it’s time to save the file on your system by using the file.mv() method provided by the middleware.

The mv() method will send the file from the temporary path to the path you specified as its parameter.

The method accepts two parameters:

  • A path string where the file will be moved
  • A callback function that will be executed once the move process is finished

The method also sends the error object to the callback function, so you can use an if block to check if the process throws an error.

Here’s the complete code for moving the file under your system:

app.post("/upload", (req, res) => {
  if (!req.files) {
    return res.status(400).send("No files were uploaded.");
  }

  const file = req.files.myFile;
  const path = __dirname + "/files/" + file.name;

  file.mv(path, (err) => {
    if (err) {
      return res.status(500).send(err);
    }
    return res.send({ status: "success", path: path });
  });
});

The path of your file will be located at the files/ folder under your project directory.

With your Express server and HTML page ready, it’s time to get the server online by running node app.js command:

node app.js

Once your Express server is online. Open your browser and head to the address to see the HTML page you’ve created previously.

When you upload a file and submit the form, an ENOENT error will occur because the files/ folder does not exist.

Here’s an example of my error:

{
  "errno":-2,
  "code":"ENOENT",
  "syscall":"open",
  "path":"/Users/nsebhastian/Desktop/test/files/image.png"
}

To prevent the ENOENT error, you need to create the files/ folder manually in your project folder.

Alternatively, you can also set the createParentPath option to true when you call the fileUpload() function inside app.use() method.

The option will let express-fileupload create the directory path for mv() method when it doesn’t exist:

app.use(
  fileUpload({
    createParentPath: true,
  })
);

And now you should be able to upload your file just fine.

Validating file requirements with express-fileupload

You can also validate the file being send from the request by utilizing the properties addded by express-fileupload middleware.

For example, you can check the file extension and only allow image extensions like .jpg and .png as shown below:

const file = req.files.myFile;
const extensionName = path.extname(file.name); // fetch the file extension
const allowedExtension = ['.png','.jpg','.jpeg'];

if(!allowedExtension.includes(extensionName)){
    return res.status(422).send("Invalid Image");
}

You can also check if the uploaded file size is above a certain limit by setting the limits option inside the fileUpload() call.

The example below will set the file size limit to 1 MB and abort the request process by returning an HTTP 413 response when the file exceeds the limit.

 app.use(fileUpload({
    limits: {
        fileSize: 1024 * 1024 // 1 MB
    },
    abortOnLimit: true
 }));

The file size limit is set in bytes.

Handling multiple files upload using express-fileupload

The express-fileupload handle multiple files upload by assigning each file to the req.files object.

Suppose you have an HTML with three file <input> elements as follows:

<form method="POST" action="/upload" enctype="multipart/form-data">
  <input type="file" name="myFile" />
  <input type="file" name="myPicture" />
  <input type="file" name="myVideo" />
  <input type="submit" />
</form>

You can retrieve the uploaded files from the req.files.[name] as shown below:

app.post("/upload", (req, res) => {
  console.log(req.files.myFile);
  console.log(req.files.myPicture);
  console.log(req.files.myVideo);
});

Just like in the single upload example, you need to take note of the name attribute you used in your HTML page.

Conclusion

The express-fileupload library is a minimalist Express framework middleware that does exactly what the name implies.

The middleware provides you with properties, methods and configurations to validate files send through a POST request and save them in your filesystem.

For more information, check out the express-fileupload Github page.

Take your skills to the next level ⚡️

I'm sending out an occasional email with the latest tutorials on programming, web development, and statistics. Drop your email in the box below and I'll send new stuff straight into your inbox!

No spam. Unsubscribe anytime.