Multer is a body parsing middleware that handles content type multipart/form-data.
- A Basic Usage
- A Basic Express App
- Install
- Create This Project Structure
- Initialize it / Import it
- Add Destination Folder & File Name
- Storing SINGLE
- Storing MULTIPLE
- MULTER NOTES:
- File has these informations:
- Multer ARRAY
- How to show images in web?
- // formupload.jsx (merge the code with already formupload.jsx)
- For Replacing that old image —– replacing old pathname, deleting old image and adding new pathname, adding new image.
- ———————————
- Let's Add destination folder & file name
- Creating an upload route (i.e. POST Route)
- FINSIHED !!!
- Creating a Frontend for File Upload
- Final Code
A Basic Usage
Don’t forget the enctype="multipart/form-data"
in your form.
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
A Basic Express App
Prerequisite: Make sure you have a running Basic Express App.
Install
npm i multer
Create This Project Structure
- index.js
- multer.js
- routes/ router.js
Initialize it / Import it
// multer.js
const multer = require('multer') // Intialize the MULTER
const path = require('path'); // Don't forget to require 'path'
Add Destination Folder & File Name
file’s name and validation regarding the type of file. file’s destinatio folder too.
//multer.js
const multer = require('multer');
const path = require('path'); // Don't forget to require 'path'
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, 'uploads')); // Store files in a project root's relative 'uploads' folder
},
// ImageName-2024-10-17-13-45-23.jpg [Original Name + Date + Time] // THIS IS YOUR FILE NAME
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
// ------------ERROR NOTE:------------------------------------------------
//
// Don't do this or it will give this error ( Error: ENOENT: no such file or directory, open 'C:\uploads\images-2024-10-28-20-48-10.png' )
//
// destination: function (req, file, cb) {
// cb(null, '/uploads') // this is your DESTINATION FOLDER
// },
When using route, make sure to do:
// routes/router.js
// routes/router.js
const express = require('express')
const router = express.Router()
const upload = require('../multer.js') // IMPORTING MULTER TO USE IT ( MUST DO THIS )
//
// YOUR CODE OF GET, POST, PUT, DELETE ROUTES
//
module.exports = router
And do this in index.js
const upload=require('./multer.js')
const router=require('./routes/router.js')
// index.js
const express=require('express')
const cors = require('cors')
const upload=require('./multer.js') // (((((((( DO THIS ))))))))
const router=require('./routes/router.js') // (((((( DO THIS TOO )))))))
// Initialize Express Application
const app = express()
// Apply Middlewares
app.use(cors()) // ensure all requests respect cross-origin rules
app.use(express.json()) //parses all JSON requests/bodies going to routes
app.use('/uploads', express.static('uploads')) // serving uploads folder
// Use the routes
app.use(router)
const PORT = 8000
app.listen(PORT, () => {
console.log(`Backend Server is running on port ${PORT}`)
});
Storing SINGLE
Using upload.single()
is particularly useful when your application requires only one file upload, such as for user avatars, profile pictures, or similar use cases.
// 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
Using upload.array()
is particularly useful when you need to handle multiple file uploads from a single input field, such as for gallery uploads, batch uploads, or similar functionalities.
POST ROUTE
// 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 });
});
});
PUT ROUTE
MULTER NOTES:
req.file stores the file
req.body stores the text fields, if there were any
File has these informations:
File information
Each file contains the following information:
Key | Description | Note |
---|---|---|
fieldname (req.file.fieldname) | Field name specified in the form | Ex: <input type=”file” class=”form-control-file” name=”uploaded_file” > |
originalname (req.file.originalname) | Name of the file on the user’s computer | |
encoding | Encoding type of the file | which character encoding was done in text content? UTF-8 | ISO-8859-1 | ASCII |
mimetype (req.file.mimetype) | Mime type of the file | Output: image/jpeg |
size (req.file.size) | Size of the file in bytes | |
destination (req.file.destination) | The folder to which the file has been saved | DiskStorage |
filename (req.file.filename) | The name of the file within the destination | DiskStorage |
path (req.file.path) | The full path to the uploaded file | DiskStorage |
buffer | A Buffer of the entire file | MemoryStorage |
Multer 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")
})
Multer ARRAY
app.post("/upload", upload.array("file", 10), (req, res) => {
console.log(req.files)
return res.send("Multiple files")
})
How to show images in web?
Serve uploaded Images as static files
This makes sure to serve the directory where images are stored.
// index.js
app.use('/uploads', express.static('uploads'));
// formupload.jsx (merge the code with already formupload.jsx)
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function ANYTHING() {
ย ย ย ย const [products, setProducts] = useState([]);
ย ย ย ย
ย // Fetch product data from backend
useEffect(() => {
ย ย const fetchProducts = () => {
ย ย ย ย axios.get('http://localhost:5000/upload')
ย ย ย ย ย ย .then((response) => {
ย ย ย ย ย ย ย ย setProducts(response.data); // Store all reponse data to 'products'
ย ย ย ย ย ย })
ย ย ย ย ย ย .catch((error) => {
ย ย ย ย ย ย ย ย console.error('Error fetching products:', error);
ย ย ย ย ย ย });
ย ย };
ย ย fetchProducts(); // Call the function to fetch products
}, []);
ย ย ย ย return (
ย ย ย ย ย ย <div>
ย ย ย ย ย ย ย ย <h2>Product List</h2>
ย ย ย ย ย ย ย ย <ul>
ย ย ย ย ย ย ย ย
ย ย ย ย ย ย ย ย ย ย {products.map((product) => (
ย ย ย ย ย ย ย ย ย ย ย <li key={product.id}>
ย ย ย ย ย ย ย ย ย ย ย ย ย ย <p><strong>Card Title:</strong> {product.cardTitle}</p>
ย ย ย ย ย ย ย ย ย ย ย ย ย ย <p><strong>Brand:</strong> {product.brand}</p>
ย ย ย ย ย ย ย ย ย ย ย ย ย ย
ย ย ย ย ย ย ย ย ย ย ย ย {product.displayImage && (
ย ย ย ย ย ย ย ย ย ย ย ย ย ย <imgย
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย src={`http://localhost:5000/${product.displayImage}`}ย
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย alt={product.cardTitle}ย
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย style={{ width: '100px' }} // Adjust size as needed
ย ย ย ย ย ย ย ย ย ย ย ย ย />
ย ย ย ย ย ย ย ย ย ย ย ย )}
ย ย ย ย ย ย ย ย ย ย ย ย </li>
ย ย ย ย ย ย ย ย ย ย ))}
ย ย ย ย ย ย ย ย </ul>
ย ย ย ย ย ย </div>
ย ย ย ย );
ย ย }
for text
<p><strong>Card Title:</strong> {product.cardTitle}</p>
for image
{product.displayImage && (
ย ย ย ย ย ย ย ย ย ย ย ย ย ย <imgย
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย src={`http://localhost:5000/${product.displayImage}`}ย
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย alt={product.cardTitle}ย
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย style={{ width: '100px' }} // Adjust size as needed
ย ย ย ย ย ย ย ย ย ย ย ย ย ย />
ย )}
For Replacing that old image —– replacing old pathname, deleting old image and adding new pathname, adding new image.
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const router = express.Router();
// Configure Multer storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1E9)}`;
cb(null, `${file.fieldname}-${uniqueSuffix}${path.extname(file.originalname)}`);
},
});
const upload = multer({ storage });
// Update image route
router.put('/update-image/:id', upload.single('image'), (req, res) => {
const { id } = req.params;
const newImage = req.file;
// Simulate checking the existing image (e.g., from DB or local file path)
const existingImagePath = `uploads/${id}.jpg`; // Assume images are stored as 'id.jpg'
// Delete old image (optional step)
if (fs.existsSync(existingImagePath)) {
fs.unlinkSync(existingImagePath);
}
// New image is now uploaded to `uploads/` directory
res.json({ message: 'Image updated successfully', file: newImage });
});
module.exports = router;
———————————
If you want to upload a single image at a time, then follow these steps.
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