Create Node Express & Multer File Upload & Download REST API

Throughout this step by step tutorial, you will learn how to create file upload REST API with Node and Express js. You will also find out how to use multer in Node.js for handling multipart/form-data for uploading files.

Also, you will learn to create REST APIs for:

  • File uploading
  • Getting Files information
  • Downloading files list

This Node.js Express Rest API for file uploading example will provide solutions for file uploading to a static folder within the server’s locus.

You will learn how to set the file size limit, downloading a file from the server with a file downloading link. Moreover, you will also find out how to get uploaded files collection with files information such as the name & url of the files.

Node Js REST API File Upload Example

  • Create Node File Upload Project
  • Build File Upload Middleware
  • Create File Storage Folder
  • Multer File Size Validation
  • Multer File Extension Validation in Node
  • Create File Upload Controller
  • Create File Uploading REST API Routes
  • Build Express Server
  • Test Node Express File Upload REST API

Create Node File Upload App

npm install express cors multer

Create File Upload Middleware

The file upload middleware takes the pain out of handling file uploading using multer package for multipart/form-data.

Create a middleware folder go inside the folder and create fileUpload.js file by using the given below command:

mkdir middleware && cd middleware && touch fileUpload.js

Next, add the following code in middleware/fileUpload.js file:

const util = require("util");
const multer = require("multer");

const DIR = './public/uploads/';

let storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, DIR);
    },
    filename: (req, file, cb) => {
        const fileName = file.originalname.toLowerCase().split(' ').join('-');
        cb(null, fileName)
    },
});

let upload = multer({
    storage: storage,
    limits: {
        fileSize: 1024 * 1024 * 5
    },
    fileFilter: (req, file, cb) => {
        if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
            cb(null, true);
        } else {
            cb(null, false);
            return cb(new Error('File types allowed .jpeg, .jpg and .png!'));
        }
    }
}).single("file");

let fileUploadMiddleware = util.promisify(upload);

module.exports = fileUploadMiddleware;

We first imported util, multer modules.

The DIR const is a declaration for a file storage path.

The disk storage engine allocates complete control on storing files to disk.

The DIR const is passed to the destination, and it is responsible for storing the uploaded files.

The filename property decides the file name within the destination directory.

The util module exposes the promisify() method, which is a common library of node. That transforms a method which returns responses using a callback function and return responses as a promise object.

Create File Storage Folder

For storing the files, you have to create 'public' folder and get inside of it and also create 'uploads' folder:

mkdir public && cd public && mkdir uploads

Multer File Size Validation

The limits property handles the file size validation, in the below example we are seeing how to limit file size with multer. So, here we restrict the file uploading limit upto 5 megabytes per file.

let storage = multer.diskStorage({...});

let upload = multer({
    storage: storage,
    limits: {
        fileSize: 1024 * 1024 * 5
    },
    fileFilter: (req, file, cb) => {...}
}).single("file");

Multer File Extension Validation in Node

The fileFilter property exposes to mimetype, which helps implement the file extension or file type validation for specific file types or extensions.

For instance, you can only upload png, jpg, and jpeg in this example; however, if the condition is not matched, then the error message will be displayed for the wrong file type.

let storage = multer.diskStorage({...});

let upload = multer({
    storage: storage,
    limits: {...},
    fileFilter: (req, file, cb) => {
        if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
            cb(null, true);
        } else {
            cb(null, false);
            return cb(new Error('File types allowed .jpeg, .jpg and .png!'));
        }
    }
}).single("file");

Create File Upload Controller

Create a controller folder get into the directory, next create fileUpload.controller.js file by using the following command:

mkdir controller && cd controller && touch fileUpload.controller.js

Next, add the following code in controller/fileUpload.controller.js:

const upload = require("../middleware/fileUpload");

const URL = "http://localhost:8888/get-cfiles/";
const fs = require("fs");


const uploadFile = async (req, res) => {
  try {
    await upload(req, res);

    if (req.file == undefined) {
      return res.status(400).send({ message: "Choose a file to upload" });
    }

    res.status(200).send({
      message: "File uploaded successfully: " + req.file.originalname,
    });
  } catch (err) {
    console.log(err);

    if (err.code == "LIMIT_FILE_SIZE") {
      return res.status(500).send({
        message: "File size should be less than 5MB",
      });
    }

    res.status(500).send({
      message: `Error occured: ${err}`,
    });
  }
};

const getFilesList = (req, res) => {
  const path = __basedir + "/public/uploads/";

  fs.readdir(path, function (err, files) {
    if (err) {
      res.status(500).send({
        message: "Files not found.",
      });
    }

    let filesList = [];

    files.forEach((file) => {
      filesList.push({
        name: file,
        url: URL + file,
      });
    });

    res.status(200).send(filesList);
  });
};

const downloadFiles = (req, res) => {
    const fileName = req.params.name;
    const path = __basedir + "/public/uploads/";
  
    res.download(path + fileName, (err) => {
      if (err) {
        res.status(500).send({
          message: "File can not be downloaded: " + err,
        });
      }
    });
};

module.exports = { uploadFile, downloadFiles, getFilesList };

In this step, we created a business logic for file upload, downloading files list and get the files list with file information, plus this controller will be the standard locus for node file uploading example.

Import file upload middleware at the beginning.

Next, declare the upload() function which is being powered by multer. A successful file uploading would notify a message to the user similarly an error message if the error occurred.

This controller file also adds the multer file size limit error using the LIMIT_FILE_SIZE property; it will throw the error of file size with the catch() method.

Create File Uploading REST API Routes

Create a routes folder get into the directory, next create upload.route.js file by using the following command:

mkdir routes && cd routes && touch upload.route.js

Next, add the following code in routes/upload.route.js:

const express = require("express");
const router = express.Router();

const controller = require("../controller/fileUpload.controller");

let routes = (app) => {
  router.post("/upload-file", controller.uploadFile)

  router.get("/files", controller.getFilesList)

  router.get("/files/:name", controller.downloadFiles)

  app.use(router);
};

module.exports = routes;

Build Express Server

In this step, you have to create an index.js file inside the root of your node project.

Further, open and update the following code in index.js file:

const express = require("express");
const cors = require("cors");
const app = express();

global.__basedir = __dirname;

var corsConfig = {
  origin: "http://localhost:8888"
};

app.use(cors(corsConfig));

const evokeRoutes = require("./routes/upload.route");

app.use(express.urlencoded({ 
  extended: true 
}));

evokeRoutes(app);

const port = process.env.PORT || 8888;
app.listen(port, () => {
  console.log('Connected to port ' + port)
})

// Handle error
app.use((req, res, next) => {
  setImmediate(() => {
    next(new Error('Error occured'));
  });
});

app.use(function (err, req, res, next) {
  console.error(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
});

Test Node Express File Upload REST API

For testing the Node File Upload REST API, you have to execute the below command from the project root:

node index.js

Start Postman application and here is the list of the REST APIs with their respective HTTP methods, that you can test now:

Base url: http://localhost:8888

HTTP Method API
POST /upload-file
GET /files
GET /files/[FILE_Name]

Call HTTP POST request for uploading file:

Call HTTP POST request for uploading file

Test larger file size validation:

Test larger file size validation

Here are the files we have uploaded, now you can check them on the public/uploads directory:

uploaded files

Further, you will see how to fetch list of files using node REST API. Do not forget to change the HTTP method to GET:

fetch list of files

From the uploaded files list, you can download specific file. You just have to append the file name at the end of the url localhost:8888/files/:name:

http://localhost:8888/files/sample.png

Conclusion

This tutorial is over, in this tutorial, you have learned how to build REST API for file uploading, download the file list, and get files information using Node.js, Express.js and Multer.

We have also found out how to restrict file size from file uploading and how to restrict file extension for file uploading. I reckon you will like this tutorial and will share this tutorial other developers.

Also download the full code from GitHub.

Tutorial reference from: bezkoder.