Multer is a middleware.
Multer is a body parsing middleware that handles content type multipart/form-data.
Multer for uploading Single Image
If you want to upload a single image at a time, then follow these steps:
Prerequesites
Make sure you have a running Basic Express App.
Install
npm install multer
import the multer into our server.js file
const multer = require("multer")
Let’s Add destination folder & file name
In this, we will set file’s name, destination, add validation regarding the type of the file.
ADD DESTINATION FOLDER
METHOD 1:
If you use this method, you have to create a folder.
Create ‘uploads’ folder — here we will store the uploaded files.
// server.js
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads/") // destination folder
}
})
METHOD 2:
With this method, you don’t have to create “uploads” folder, it will automatically create that folder for you.
// server.js
const fs = require('fs');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
const dir = 'uploads/';
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
cb(null, dir);
},
});
Note: We need a package called “fs” so that we could have control over directory and check whether “uploads” folder exists or not — and finally create the”uploads” folder. We don’t need to install fs module because it’s built-in core module, so we can use it without any installation.
This line “if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });” checks whether the directory exists or not, if it doesn’t exist, it will create that folder.
This line “cb(null, dir);” sets the destination folder for the file given in dir variable.
ADD FILE NAME
This file name can be applicable for all files including photos, pdf documents, and videos.
Note: Because we are using path (e.g: path.extname), so we need to import that package too. You don’t need to install the path module in Node.js because it is a built-in module. You can use it directly without any installation.
const path = require('path');
Original Name + Timestamp
filename: (req, file, cb) => {
cb(null, file.originalname.split('.')[0] + '-' + Date.now() + path.extname(file.originalname));
}
Output: ImageName-1727337530899.jpg
Format: [originalNameWithoutExtension]-[timestamp][originalExtension]
file.originalname.split('.')[0] - Original Name of File without extension
Date.now() - Get current timestamp in milliseconds from epoch era
path.extname(file.originalname) - Get file extension
Original Name + Date + Time
filename: (req, file, cb) => {
const originalName = file.originalname.split('.')[0]; // Extract name without extension
const date = new Date();
const formattedDate = date.toISOString().split('T')[0]; // Format: YYYY-MM-DD
const formattedTime = date.toTimeString().split(' ')[0].replace(/:/g, '-'); // Format: HH-MM-SS
const newFilename = `${originalName}-${formattedDate}-${formattedTime}${path.extname(file.originalname)}`;
cb(null, newFilename);
}
Output: ImageName-2024-10-17-13-45-23.jpg
ALL PIECES TOGETHER
I have used Method 2 of Destination Folder and 2nd Option for File Name.
const multer = require('multer');
const fs = require('fs'); // // Don't forget to require 'fs'
const path = require('path'); // Don't forget to require 'path'
const storage = multer.diskStorage({
destination: (req, file, cb) => {
const dir = 'uploads/';
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
cb(null, dir);
},
filename: (req, file, cb) => {
const originalName = file.originalname.split('.')[0]; // Extract name without extension
const date = new Date();
const formattedDate = date.toISOString().split('T')[0]; // Format: YYYY-MM-DD
const formattedTime = date.toTimeString().split(' ')[0].replace(/:/g, '-'); // Format: HH-MM-SS
const newFilename = `${originalName}-${formattedDate}-${formattedTime}${path.extname(file.originalname)}`;
cb(null, newFilename);
},
});
var upload = multer({ storage: storage }); // Initialize multer with the storage configuration
module.exports = upload; // Export upload middleware for use in your routes
Note: We don’t need to install fs and path modules because they are built-in core modules, so we can use them without any installation.
Output: Your files will be stored in uploads folder with file name structure [ Original Name + Date + Time ]
Creating an upload route (i.e. POST Route)
Storing SINGLE
// Single file (receives only a single file)
app.post("/upload", upload.single("file"), (req, res) => {
console.log(req.file)
return res.send("Single file")
})
// POST route to handle image upload and form submission
app.post('/upload', upload.single('image'), (req, res) => {
const imagePath = req.file ? req.file.path : null; // Path to the uploaded file
const { cardTitle, brand } = req.body;
// SQL query to insert form data and image path into MySQL
const query = `
INSERT INTO my_db (cardTitle, brand, displayImage, imageAddress)
VALUES (?, ?, ?, ?)
`;
db.query(query, [cardTitle, brand, imagePath, req.file.filename], (err, result) => {
if (err) {
console.error('Error inserting data:', err);
return res.status(500).json({ message: 'Error inserting data' });
}
res.json({ message: 'Product added successfully!' });
});
});
Storing MULTIPLE
//Multiple files ( receives several files, but we can set the maximum limit files [for ex: 10 max limit] )
app.post("/upload", upload.array("file", 10), (req, res) => {
console.log(req.files)
return res.send("Multiple files")
})
// POST route to handle image upload and save the image paths and inputs to MySQL
app.post('/upload', upload.array('images', 11), (req, res) => {
const files = req.files;
// Prepare an object to hold image paths for each specified column
const imageData = {
displayImage: files[0] ? files[0].path : null,
firstImage: files[1] ? files[1].path : null,
secondImage: files[2] ? files[2].path : null,
thirdImage: files[3] ? files[3].path : null,
fourthImage: files[4] ? files[4].path : null,
fifthImage: files[5] ? files[5].path : null,
sixthImage: files[6] ? files[6].path : null,
seventhImage: files[7] ? files[7].path : null,
eighthImage: files[8] ? files[8].path : null,
ninthImage: files[9] ? files[9].path : null,
tenthImage: files[10] ? files[10].path : null,
};
// Extract additional input fields from the request body
const {
slug,
cardTitle,
category,
brand,
soldNumber,
actualPrice,
markedPrice,
rating,
freeShipping,
stockStatus,
title,
description,
bigDescription,
specification
} = req.body;
// SQL query to insert image paths and other input fields into the database
const query = `
INSERT INTO my_db (
displayImage, firstImage, secondImage, thirdImage, fourthImage,
fifthImage, sixthImage, seventhImage, eighthImage, ninthImage,
tenthImage, slug, cardTitle, category, brand, soldNumber,
actualPrice, markedPrice, rating, freeShipping, stockStatus,
title, description, bigDescription, specification
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
// Execute the query with the values from imageData and input fields
db.query(query, [
imageData.displayImage, imageData.firstImage, imageData.secondImage,
imageData.thirdImage, imageData.fourthImage, imageData.fifthImage,
imageData.sixthImage, imageData.seventhImage, imageData.eighthImage,
imageData.ninthImage, imageData.tenthImage,
slug, cardTitle, category, brand, soldNumber,
actualPrice, markedPrice, rating, freeShipping, stockStatus,
title, description, bigDescription, specification
], (err, result) => {
if (err) {
console.error('Error saving data to database:', err);
return res.status(500).json({ message: 'Error saving data to database' });
}
// Send success response
res.json({ message: 'Images and data uploaded and saved successfully!', imageData });
});
});
FINSIHED !!!
Creating a Frontend for File Upload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<h1>File Upload Example</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">Upload File</button>
</form>
</body>
</html>
form fields upload
image upload
video upload
pdf upload
folder upload