How to upload file using ExpressJS(NodeJS) - Multer
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
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.
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);
});
And That's how I solved this issue. Let me know if you have any doubt.
follow me for more such blog posts.