Hemendra Khatik
aamchora

aamchora

How to upload file using ExpressJS(NodeJS) - Multer

Hemendra Khatik's photo
Hemendra Khatik
·Jul 11, 2022·

4 min read

Subscribe to my newsletter and never miss my upcoming articles

It took me 4-days and 100+ attempts to solve this simple issue of uploading a file using node.

And the moment I got it right, I was like...phewww

phew gif

Here is how I solved this issue.

By creating a -

  • Simple node server.
  • Middleware to process files.
  • POST route to accept files.
  • Route to serve files.
  • Middleware to Handle CORS issue(you won't get this issue in postman).

Node server using express

  • Initialize the project using below command

node init

  • Install the required dependencies.

using npm -> npm i express dotenv

using yarn -> yarn add express dotenv

  • Create server.js and paste below code

const express = require("express");
const dotenv = require("dotenv");

const app = express();

dotenv.config(); // <-- To use.env file

app.use(express.json());
/*
express.json() middleware helps us to parse all HTTP requests

like --> req.body

And express.json() middleware always should be at the top

*/

const PORT = process.env.PORT || 5000;
app.listen(
  PORT,
  console.log(`Server is up and running on port ${PORT}`)
);

Now run the node server using below command

node server.js

Create a middleware to process files.

Install the dependencies

using npm -> npm i multer

using yarn -> yarn add multer

Create processFile.js file and paste below code in it and create upload folder to store uploaded files in it.

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

const MIME_TYPES = {
  "image/jpg": "jpg",
  "image/jpeg": "jpg",
  "image/png": "png",
  // you can add more here
};

const storage = multer.diskStorage({
  destination: (req, file, callback) => {
    callback(null,path.join(__dirname, './upload'));
   // Note ./upload path should be relative. Change this path according to your folder structure
  },
  filename: (req, file, callback) => {
    const name = file.originalname.split(" ").join("_");
    const extension = MIME_TYPES[file.mimetype];
    callback(null, name + Date.now() + "." + extension);
  },
});

const processFile = multer({ storage: storage }).single("file"); //<--here `file` key
/*
Look at the last example of how we will use `file` key to 
upload files using form data and postman.

For accepting multiple files change above line to 

const processFile = multer({ storage: storage }).array('file', 12);
Where 12 is the number of files you want to accept.

*/

module.exports = processFile;

Create a POST route to accept file.

Paste below code in server.js file

For uploading single file

const processFile = require("./processFile");

app.post("/api/upload", processFile, (req, res, next) => {

  const url = req.protocol + "://" + req.get("host");

  const file = url + "/files/" + req.file.filename;

  res.status(201).json({
    message: "Success",
    file: file,
  });
});

For uploading multiple files

const processFile = require("./processFile");

app.post("/api/upload", processFile, (req, res, next) => {
  const files = []
  const url = req.protocol + "://" + req.get("host");
  req.files.forEach(file=>{
    const file_url = url + "/files/" + file.filename;
    files.push({
      url: file_url,
    });
  })

  res.status(201).json({
    message: "files saved successfully!",
    files,
  });
});

So far you would be able to store files in your upload folder but you can't access files using links you are receiving in the response and for that, we need to serve those files.

Serve uploaded files

Add below code in server.js file and restart the server.

const path = require("path");

app.use("/files", express.static(path.join(__dirname, "upload")));

Now you should be able to see the files if you visit the links.

CORS (Cross-Origin Resource Sharing)

Note: You won't face this issue in the postman but in your client-side app you will face this issue.

cors error

To resolve the CORS issue

  • Create a cors middleware.
  • Apply cors middleware at the top of your file

const cors = (req, res, next) => {
  const origin = "*"; // <-- change this in production
  res.setHeader("Access-Control-Allow-Origin", origin);
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content, Accept, Content-Type, Authorization"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, DELETE, PATCH, OPTIONS"
  );
  next();
};

app.use(cors); // <-- Should be at the top

Upload file from client


  const data = new FormData();
  data.append("file", FILE_URI);

  fetch("http://localhost:5000/api/upload", {
    method: "post",
    body: data,
  })
  .then((res) => res.json())
  .catch((err) => {
     console.log(err);
  });

upload file using postman

And That's how I solved this issue. Let me know if you have any doubt.


follow me for more such blog posts.

Twitter || Linkedin

Did you find this article valuable?

Support Hemendra Khatik by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors