Skip to main content

Create File Upload REST API with Node.js

In our previous Node Js tutorial, we have explained how to Create REST API with Node.js, Express & MongoDB. In this tutorial, we will explain to Create File Upload REST API with Node.js.

We will use Express, Multer and CORS modules to create our REST API for uploading, listing and deleting files.

The API will cover following:

  • Uploading Files to a static folder in the Server.
  • Downloading File from Server with the link.
  • Get list of all files.
  • Get file by file name.
  • Deleting File from Server by file name.

The API end point will be following:

Methods End Point Action
POST /upload upload a File
GET /files get List of Files
GET /files/[filename] download a File
DELETE /files/[filename] delete a File

Prerequisites

  • Need Node.js development environment installed.
  • express 4.18.2
  • multer 1.4.4-lts.1.
  • cors 2.8.5

Project Structure

We have following directory and files in our project:

  • server.js: This is main server file that initializes routes and runs express app.
  • routes/index.js: This file defines routes for endpoints such as (upload, files) called from HTTP Client. We will use controller to handle requests.
  • controller/file.upload.controller.js: This is controller file in which handling POST a file, GET all files information, download a File with url.
  • middleware/upload.file.js: In this file, initializes Multer Storage engine and defines middleware function to save uploaded files in uploads directory.
  • resources/static/assets/uploads: We will store uploaded files in this directory.

Below is complete file structure of our REST API project:

Install Required Modules

We will open command prompt and move to the project direcgory. Then we will run below command to install Express, Multer and CORS modules for this prject.

npm install express multer cors

Create Middleware for File Upload

We will create middleware middleware/upload.file.js file for handling multipart/form-data along with uploading files. We will use Multer module and define max file to handle file upload.

const util = require("util");
const multer = require("multer");
const maxSize = 2 * 1024 * 1024;

let storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, __basedir + "/resources/static/assets/uploads/");
  },
  filename: (req, file, cb) => {
    console.log(file.originalname);
    cb(null, file.originalname);
  },
});

let uploadFile = multer({
  storage: storage,
  limits: { fileSize: maxSize },
}).single("file");

let uploadFileMiddleware = util.promisify(uploadFile);
module.exports = uploadFileMiddleware;

Create File Upload Controller

We will create controller/file.upload.controller.js controller file and import middleware middleware/upload.file.js and implement upload() method to handle file upload. We will implement upload(), getFiles(), download() and remove() methods.

const uploadFile = require("../middleware/upload.file");
const fs = require("fs");
const baseUrl = "http://localhost:8080/files/";

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

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

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

    if (err.code == "LIMIT_FILE_SIZE") {
      return res.status(500).send({
        message: "File size cannot be larger than 2MB!",
      });
    }

    res.status(500).send({
      message: `Could not upload the file: ${req.file.originalname}. ${err}`,
    });
  }
};

const getFiles = (req, res) => {
  const directoryPath = __basedir + "/resources/static/assets/uploads/";

  fs.readdir(directoryPath, function (err, files) {
    if (err) {
      res.status(500).send({
        message: "Unable to scan files!",
      });
    }

    let fileInfos = [];

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

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

const download = (req, res) => {
  const fileName = req.params.name;
  const directoryPath = __basedir + "/resources/static/assets/uploads/";

  res.download(directoryPath + fileName, fileName, (err) => {
    if (err) {
      res.status(500).send({
        message: "Could not download the file. " + err,
      });
    }
  });
};

const remove = (req, res) => {
  const fileName = req.params.name;
  const directoryPath = __basedir + "/resources/static/assets/uploads/";

  fs.unlink(directoryPath + fileName, (err) => {
    if (err) {
      res.status(500).send({
        message: "Could not delete the file. " + err,
      });
    }

    res.status(200).send({
      message: "File is deleted.",
    });
  });
};

const removeSync = (req, res) => {
  const fileName = req.params.name;
  const directoryPath = __basedir + "/resources/static/assets/uploads/";

  try {
    fs.unlinkSync(directoryPath + fileName);

    res.status(200).send({
      message: "File is deleted.",
    });
  } catch (err) {
    res.status(500).send({
      message: "Could not delete the file. " + err,
    });
  }
};

module.exports = {
  upload,
  getFiles,
  download,
  remove,
  removeSync,
};

Define Routes for Controller Methods

We will create routes/index.js file and setup routes or end points to handle HTTP requests for controller methods. We will use file.upload.controller.js controller and call methods on related routes.

const express = require("express");
const router = express.Router();
const controller = require("../controller/file.upload.controller");

let routes = (app) => {
  router.post("/upload", controller.upload);
  router.get("/files", controller.getFiles);
  router.get("/files/:name", controller.download);
  router.delete("/files/:name", controller.remove);

  app.use(router);
};

module.exports = routes;

Create App Server

We will add below code server.js file to create our Express server. Here we will import cors and express modules. Then creating express app and cors middleware using app.use(corsOption) method. Then set to listen on port 8080 for api requests.

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

global.__basedir = __dirname;

var corsOption = {
  origin: "http://localhost:8081"
};

app.use(cors(corsOption));

const initRoutes = require("./src/routes");

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

let listenPort = 8080;

app.listen(listenPort, () => {
  console.log(`Running at localhost:${listenPort}`);
});

Run Application and Test in Postman App

Finally, we will run our REST API application using below command.

node server.js

The application will run on port 8080. The end points can be accessed on localhost:8080 url.

We will use POSTMAN App to make HTTP requests to API to test different end points.

We will test file upload with method post (http://localhost:8080/upload):

We will test to get all files with method get (http://localhost:8080/files):

We will test to get a specific file url by name (http://localhost:8080/files/filename):

We will test to delete a file by name with method delete (http://localhost:8080/files/filename):