नमस्ते दोस्तों! 🙏
स्वागत है The Easy Master पर!
क्या तुमने कभी सोचा है – Express.js app mein user profile picture, PDF, ya document kaise upload karein?
Jab users image upload karte hain (WhatsApp, Instagram, Gmail), toh backend ko files receive karni padti हैं। Node.js by default files handle nahi karta – iske liye Multer middleware use karte hain।
Express file upload Multer Hindi में समझना बहुत जरूरी है क्योंकि:
- Profile pictures, documents, PDFs – sab upload karne padte hain
- Every real-world app mein file upload feature hota है
- Multer is the most popular file upload library (2M+ weekly downloads)
- Interview mein pakka file upload questions puche jayenge
Aaj kya seekhoge?
| Topic | Kya Seekhega? |
|---|---|
| Multer Kya Hai? | Introduction aur setup |
| Single File Upload | Ek file upload |
| Multiple Files Upload | Ek saath multiple files |
| File Validation | Type, size, extension check |
| Storage Options | DiskStorage, MemoryStorage |
| Error Handling | Upload errors handle karna |
| Image Processing | Sharp se resize/compress |
| Real Project | Profile picture upload API |
Kya tumhe pata hai?
Multer multipart/form-data format handle करता है – jo HTML forms mein file upload के लिए use होता है!
तो चलिए शुरू करते हैं – Express file upload Multer Hindi सीखने का सफर! 🚀
Table of Contents
1. File Upload क्या Hai? – Introduction
File upload client se server tak files bhejne की process है।
Without Multer (Hard Way):
// ❌ Raw Node.js – very complex!
const http = require('http');
const fs = require('fs');
const formidable = require('formidable'); // alternative
// Lots of manual parsing...With Multer (Easy Way):
// ✅ Multer – simple & clean!
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('image'), (req, res) => {
res.json({ file: req.file });
});Express file upload Multer Hindi में हम complete setup सीखेंगे।
2. Multer Setup – Installation aur Configuration
Step 1: Install Multer
npm install multerStep 2: Basic Setup
// server.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// Configure storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // Where to save files
},
filename: (req, file, cb) => {
// Create unique filename: timestamp-originalname
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, uniqueSuffix + path.extname(file.originalname));
}
});
// File filter (optional)
const fileFilter = (req, file, cb) => {
// Accept images only
if (file.mimetype.startsWith('image/')) {
cb(null, true);
} else {
cb(new Error('Only images are allowed!'), false);
}
};
// Create multer instance
const upload = multer({
storage: storage,
limits: {
fileSize: 5 * 1024 * 1024 // 5MB limit
},
fileFilter: fileFilter
});
// Create uploads folder if not exists
const fs = require('fs');
if (!fs.existsSync('uploads')) {
fs.mkdirSync('uploads');
}
// Routes
app.post('/upload', upload.single('image'), (req, res) => {
res.json({
message: 'File uploaded successfully!',
file: req.file
});
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});Step 3: HTML Form for Testing
<!-- public/upload.html -->
<!DOCTYPE html>
<html>
<head>
<title>File Upload</title>
<style>
body { font-family: Arial; padding: 50px; }
.container { max-width: 500px; margin: auto; }
input, button { margin: 10px 0; padding: 10px; }
button { background: #61DAFB; border: none; cursor: pointer; }
</style>
</head>
<body>
<div class="container">
<h1>Upload File</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="image" accept="image/*" required>
<br>
<button type="submit">Upload</button>
</form>
</div>
</body>
</html>3. Single File Upload – Ek File Upload Karna
Basic Single File Upload:
// server.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// Simple config (no custom filename)
const upload = multer({ dest: 'uploads/' });
// Single file upload - field name = 'file'
app.post('/upload', upload.single('file'), (req, res) => {
// req.file contains uploaded file info
// req.body contains text fields
console.log('File:', req.file);
console.log('Body:', req.body);
res.json({
success: true,
message: 'File uploaded successfully!',
file: {
originalName: req.file.originalname,
size: req.file.size,
path: req.file.path,
mimetype: req.file.mimetype
}
});
});
app.listen(3000);Complete Single Upload with Custom Config:
// config/multer.js
const multer = require('multer');
const path = require('path');
// Custom storage configuration
const storage = multer.diskStorage({
destination: (req, file, cb) => {
let folder = 'uploads/';
// Different folders for different file types
if (file.mimetype.startsWith('image/')) {
folder = 'uploads/images/';
} else if (file.mimetype === 'application/pdf') {
folder = 'uploads/pdfs/';
} else {
folder = 'uploads/documents/';
}
cb(null, folder);
},
filename: (req, file, cb) => {
// Create unique filename
const timestamp = Date.now();
const random = Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
const basename = path.basename(file.originalname, ext);
// Sanitize filename (remove spaces, special chars)
const sanitized = basename.replace(/[^a-zA-Z0-9]/g, '_');
const filename = `${timestamp}-${random}-${sanitized}${ext}`;
cb(null, filename);
}
});
// File filter
const fileFilter = (req, file, cb) => {
const allowedTypes = [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error(`File type ${file.mimetype} is not supported`), false);
}
};
// Multer instance
const upload = multer({
storage: storage,
limits: {
fileSize: 10 * 1024 * 1024 // 10MB
},
fileFilter: fileFilter
});
module.exports = upload;// routes/upload.js
const express = require('express');
const router = express.Router();
const upload = require('../config/multer');
const fs = require('fs');
const path = require('path');
// Ensure upload directories exist
const createDir = (dir) => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
};
createDir('uploads/images');
createDir('uploads/pdfs');
createDir('uploads/documents');
// Single file upload
router.post('/file', upload.single('file'), (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
res.status(201).json({
success: true,
message: 'File uploaded successfully',
data: {
originalName: req.file.originalname,
filename: req.file.filename,
size: req.file.size,
mimetype: req.file.mimetype,
path: req.file.path,
url: `/uploads/${path.basename(req.file.path)}`
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// File with additional form data
router.post('/profile', upload.single('avatar'), (req, res) => {
const { name, email } = req.body;
const avatar = req.file;
if (!avatar) {
return res.status(400).json({ error: 'Avatar is required' });
}
res.json({
success: true,
message: 'Profile updated',
data: {
user: { name, email },
avatar: {
filename: avatar.filename,
url: `/uploads/${avatar.filename}`
}
}
});
});
module.exports = router;4. Multiple Files Upload – Ek Saath Multiple Files
Upload Multiple Files (Same field):
// Multiple files with same field name
router.post('/multiple', upload.array('files', 5), (req, res) => {
// req.files is array of files
// Max 5 files
if (!req.files || req.files.length === 0) {
return res.status(400).json({ error: 'No files uploaded' });
}
const files = req.files.map(file => ({
originalName: file.originalname,
filename: file.filename,
size: file.size,
mimetype: file.mimetype,
url: `/uploads/${file.filename}`
}));
res.json({
success: true,
message: `${files.length} files uploaded successfully`,
data: { files }
});
});Upload Multiple Files (Different fields):
// Different fields for different files
router.post('/documents', upload.fields([
{ name: 'avatar', maxCount: 1 },
{ name: 'resume', maxCount: 1 },
{ name: 'certificates', maxCount: 5 }
]), (req, res) => {
// req.files is object: { avatar: [...], resume: [...], certificates: [...] }
const response = {
avatar: req.files.avatar ? req.files.avatar[0] : null,
resume: req.files.resume ? req.files.resume[0] : null,
certificates: req.files.certificates || []
};
res.json({
success: true,
message: 'Documents uploaded successfully',
data: response
});
});HTML Form for Multiple Files:
<!-- public/multiple-upload.html -->
<!DOCTYPE html>
<html>
<head>
<title>Multiple File Upload</title>
</head>
<body>
<h1>Upload Multiple Files</h1>
<!-- Multiple files same field -->
<form action="/upload/multiple" method="POST" enctype="multipart/form-data">
<h3>Upload Multiple Images</h3>
<input type="file" name="files" multiple accept="image/*">
<button type="submit">Upload</button>
</form>
<!-- Different fields -->
<form action="/upload/documents" method="POST" enctype="multipart/form-data">
<h3>Upload Documents</h3>
<input type="file" name="avatar" accept="image/*" required>
<input type="file" name="resume" accept=".pdf,.doc,.docx" required>
<input type="file" name="certificates" multiple accept=".pdf">
<button type="submit">Upload</button>
</form>
</body>
</html>5. File Validation – Type, Size, Extension Check
Complete Validation Middleware:
// middleware/uploadValidation.js
const multer = require('multer');
const path = require('path');
// File type validation
const fileFilter = (req, file, cb) => {
const allowedImageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
const allowedDocTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
const isImage = allowedImageTypes.includes(file.mimetype);
const isDocument = allowedDocTypes.includes(file.mimetype);
if (req.query.type === 'image' && isImage) {
cb(null, true);
} else if (req.query.type === 'document' && isDocument) {
cb(null, true);
} else if (!req.query.type && (isImage || isDocument)) {
cb(null, true);
} else {
cb(new Error(`Invalid file type. Allowed: ${req.query.type === 'image' ? 'JPEG, PNG, GIF, WEBP' : 'PDF, DOC, DOCX'}`), false);
}
};
// Custom validation function
const validateFile = (req, res, next) => {
if (!req.file && !req.files) {
return res.status(400).json({ error: 'No file uploaded' });
}
// Check file size (already handled by multer limits)
// Check for viruses (can integrate ClamAV)
next();
};
module.exports = { fileFilter, validateFile };Size Validation:
// config/multer.js
const multer = require('multer');
// Size limits for different file types
const sizeLimits = {
image: 5 * 1024 * 1024, // 5MB
document: 10 * 1024 * 1024, // 10MB
video: 50 * 1024 * 1024, // 50MB
default: 5 * 1024 * 1024 // 5MB
};
const getSizeLimit = (req) => {
const type = req.query.type || 'default';
return sizeLimits[type] || sizeLimits.default;
};
const upload = multer({
storage: storage,
limits: {
fileSize: (req, file, cb) => {
const limit = getSizeLimit(req);
cb(null, limit);
}
},
fileFilter: fileFilter
});Extension Validation:
// utils/fileValidation.js
const path = require('path');
const allowedExtensions = {
images: ['.jpg', '.jpeg', '.png', '.gif', '.webp'],
documents: ['.pdf', '.doc', '.docx', '.txt'],
archives: ['.zip', '.rar', '.7z']
};
const validateExtension = (filename, type = 'images') => {
const ext = path.extname(filename).toLowerCase();
return allowedExtensions[type].includes(ext);
};
const getFileType = (mimetype) => {
if (mimetype.startsWith('image/')) return 'images';
if (mimetype === 'application/pdf') return 'documents';
if (mimetype.includes('word')) return 'documents';
if (mimetype.includes('zip')) return 'archives';
return 'other';
};
module.exports = { validateExtension, getFileType, allowedExtensions };6. Storage Options – DiskStorage vs MemoryStorage
DiskStorage (Save to Disk):
const multer = require('multer');
const path = require('path');
const diskStorage = multer.diskStorage({
destination: (req, file, cb) => {
let dest = 'uploads/';
// Dynamic destination based on file type
if (file.mimetype.startsWith('image/')) {
dest = 'uploads/images/';
} else if (file.mimetype === 'application/pdf') {
dest = 'uploads/pdfs/';
}
cb(null, dest);
},
filename: (req, file, cb) => {
// Custom filename
const unique = Date.now() + '-' + Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
cb(null, unique + ext);
}
});
const uploadDisk = multer({ storage: diskStorage });MemoryStorage (Keep in Memory – for Cloud Upload):
const multer = require('multer');
// Store file in memory (buffer)
const memoryStorage = multer.memoryStorage();
const uploadMemory = multer({
storage: memoryStorage,
limits: { fileSize: 5 * 1024 * 1024 }
});
// Upload to cloud (AWS S3, Cloudinary, etc.)
router.post('/upload-cloud', uploadMemory.single('image'), async (req, res) => {
try {
const file = req.file;
// Upload to Cloudinary
const cloudinary = require('cloudinary').v2;
const result = await cloudinary.uploader.upload_stream(
{ folder: 'myapp' },
(error, result) => {
if (error) throw error;
res.json({ url: result.secure_url });
}
).end(file.buffer);
} catch (error) {
res.status(500).json({ error: error.message });
}
});DiskStorage vs MemoryStorage:
| Feature | DiskStorage | MemoryStorage |
|---|---|---|
| Storage | Saves to disk | Keeps in RAM (buffer) |
| Use Case | Local development, direct serving | Cloud upload, processing |
| Memory Usage | Low | High (files in RAM) |
| Speed | Fast | Faster (no disk write) |
| Persistence | Yes (files saved) | No (need to save manually) |
| Best for | Direct file serving | Cloud upload, image processing |
7. Error Handling – Upload Errors Handle Karna
Multer Error Types:
// server.js
const multer = require('multer');
const upload = multer({
dest: 'uploads/',
limits: {
fileSize: 5 * 1024 * 1024 // 5MB
},
fileFilter: (req, file, cb) => {
if (file.mimetype.startsWith('image/')) {
cb(null, true);
} else {
cb(new Error('Only images are allowed!'), false);
}
}
});
// Error handling middleware for multer
app.post('/upload', (req, res) => {
upload.single('image')(req, res, (err) => {
if (err instanceof multer.MulterError) {
// Multer-specific errors
if (err.code === 'FILE_TOO_LARGE') {
return res.status(400).json({
error: 'File too large! Maximum size is 5MB'
});
}
if (err.code === 'LIMIT_FILE_COUNT') {
return res.status(400).json({
error: 'Too many files!'
});
}
if (err.code === 'LIMIT_UNEXPECTED_FILE') {
return res.status(400).json({
error: 'Unexpected field name!'
});
}
return res.status(400).json({ error: err.message });
}
if (err) {
// Custom errors from fileFilter
return res.status(400).json({ error: err.message });
}
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded!' });
}
res.json({ success: true, file: req.file });
});
});Global Error Handler:
// middleware/errorHandler.js
const errorHandler = (err, req, res, next) => {
// Multer errors
if (err instanceof multer.MulterError) {
const errors = {
'LIMIT_FILE_SIZE': 'File too large. Maximum size is 5MB.',
'LIMIT_FILE_COUNT': 'Too many files.',
'LIMIT_UNEXPECTED_FILE': 'Unexpected field name.',
'LIMIT_PART_COUNT': 'Too many parts.',
'LIMIT_FIELD_KEY': 'Field name too long.',
'LIMIT_FIELD_VALUE': 'Field value too long.',
'LIMIT_FIELD_COUNT': 'Too many fields.',
'MIME_TYPE_NOT_SUPPORTED': 'File type not supported.'
};
return res.status(400).json({
success: false,
error: errors[err.code] || err.message,
code: err.code
});
}
// Custom validation errors
if (err.message === 'Only images are allowed!') {
return res.status(400).json({
success: false,
error: err.message
});
}
// Default error
res.status(500).json({
success: false,
error: 'Internal server error'
});
};
module.exports = errorHandler;8. Image Processing – Sharp Se Resize/Compress
Install Sharp:
npm install sharpImage Processing Middleware:
// middleware/imageProcessor.js
const sharp = require('sharp');
const path = require('path');
const fs = require('fs');
const processImage = async (req, res, next) => {
if (!req.file) {
return next();
}
try {
const filePath = req.file.path;
const ext = path.extname(req.file.originalname);
const dir = path.dirname(filePath);
const basename = path.basename(filePath, ext);
// Create different sizes
const sizes = {
thumbnail: 150,
small: 300,
medium: 600,
large: 1200
};
for (const [size, width] of Object.entries(sizes)) {
const outputPath = path.join(dir, `${basename}-${size}${ext}`);
await sharp(filePath)
.resize(width, null, { // width, height=auto
withoutEnlargement: true,
fit: 'cover'
})
.jpeg({ quality: 80 })
.toFile(outputPath);
}
// Compress original
const compressedPath = path.join(dir, `${basename}-compressed${ext}`);
await sharp(filePath)
.jpeg({ quality: 70 })
.png({ quality: 70 })
.toFile(compressedPath);
req.processedImages = {
original: req.file.path,
compressed: compressedPath,
thumbnail: path.join(dir, `${basename}-thumbnail${ext}`),
small: path.join(dir, `${basename}-small${ext}`),
medium: path.join(dir, `${basename}-medium${ext}`),
large: path.join(dir, `${basename}-large${ext}`)
};
next();
} catch (error) {
console.error('Image processing error:', error);
next(error);
}
};
module.exports = processImage;Using Image Processor:
// routes/image.js
const express = require('express');
const router = express.Router();
const multer = require('multer');
const upload = multer({ dest: 'uploads/temp/' });
const processImage = require('../middleware/imageProcessor');
router.post('/upload', upload.single('image'), processImage, (req, res) => {
res.json({
success: true,
message: 'Image uploaded and processed successfully',
data: {
original: `/uploads/${path.basename(req.processedImages.original)}`,
compressed: `/uploads/${path.basename(req.processedImages.compressed)}`,
thumbnail: `/uploads/${path.basename(req.processedImages.thumbnail)}`,
small: `/uploads/${path.basename(req.processedImages.small)}`,
medium: `/uploads/${path.basename(req.processedImages.medium)}`,
large: `/uploads/${path.basename(req.processedImages.large)}`
}
});
});
module.exports = router;9. File Download – Uploaded Files Serve Karna
Serve Static Files:
// server.js
const express = require('express');
const path = require('path');
// Serve uploaded files statically
app.use('/uploads', express.static('uploads'));
// Now files can be accessed at:
// http://localhost:3000/uploads/filename.jpgDownload Endpoint:
// routes/download.js
const express = require('express');
const router = express.Router();
const path = require('path');
const fs = require('fs');
// Download file by filename
router.get('/file/:filename', (req, res) => {
const filename = req.params.filename;
const filepath = path.join(__dirname, '../uploads', filename);
// Check if file exists
if (!fs.existsSync(filepath)) {
return res.status(404).json({ error: 'File not found' });
}
// Download with original name (from database)
res.download(filepath, filename);
});
// Download with custom name
router.get('/download/:filename', (req, res) => {
const filename = req.params.filename;
const filepath = path.join(__dirname, '../uploads', filename);
res.download(filepath, 'custom-name-' + filename, (err) => {
if (err) {
console.error('Download error:', err);
res.status(500).json({ error: 'Download failed' });
}
});
});
// Get file info
router.get('/info/:filename', (req, res) => {
const filename = req.params.filename;
const filepath = path.join(__dirname, '../uploads', filename);
if (!fs.existsSync(filepath)) {
return res.status(404).json({ error: 'File not found' });
}
const stats = fs.statSync(filepath);
res.json({
filename: filename,
size: stats.size,
created: stats.birthtime,
modified: stats.mtime,
url: `/uploads/${filename}`
});
});
module.exports = router;10. Real-world Project – Profile Picture Upload API
Complete Profile Picture Upload System:
// config/multer.js
const multer = require('multer');
const path = require('path');
const fs = require('fs');
// Ensure upload directory exists
const uploadDir = 'uploads/avatars';
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, uploadDir);
},
filename: (req, res, cb) => {
const userId = req.user?.id || 'anonymous';
const timestamp = Date.now();
const ext = path.extname(file.originalname);
cb(null, `user-${userId}-${timestamp}${ext}`);
}
});
const fileFilter = (req, file, cb) => {
const allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (allowed.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Only JPEG, PNG, GIF, and WEBP images are allowed'), false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 2 * 1024 * 1024 // 2MB
},
fileFilter: fileFilter
});
module.exports = upload;// middleware/avatarProcessor.js
const sharp = require('sharp');
const path = require('path');
const fs = require('fs');
const processAvatar = async (req, res, next) => {
if (!req.file) {
return next();
}
try {
const filePath = req.file.path;
const dir = path.dirname(filePath);
const basename = path.basename(filePath, path.extname(filePath));
const ext = '.jpg'; // Convert all to JPG for consistency
// Create optimized avatar
const optimizedPath = path.join(dir, `${basename}-optimized${ext}`);
await sharp(filePath)
.resize(400, 400, {
fit: 'cover',
position: 'center'
})
.jpeg({ quality: 85 })
.toFile(optimizedPath);
// Create thumbnail
const thumbnailPath = path.join(dir, `${basename}-thumb${ext}`);
await sharp(filePath)
.resize(100, 100, {
fit: 'cover',
position: 'center'
})
.jpeg({ quality: 70 })
.toFile(thumbnailPath);
// Delete original file
fs.unlinkSync(filePath);
req.avatar = {
original: req.file.originalname,
optimized: `/uploads/avatars/${path.basename(optimizedPath)}`,
thumbnail: `/uploads/avatars/${path.basename(thumbnailPath)}`
};
next();
} catch (error) {
console.error('Avatar processing error:', error);
next(error);
}
};
module.exports = processAvatar;// routes/profile.js
const express = require('express');
const router = express.Router();
const upload = require('../config/multer');
const processAvatar = require('../middleware/avatarProcessor');
const { authenticate } = require('../middleware/auth');
// Update profile picture
router.post('/avatar',
authenticate,
upload.single('avatar'),
processAvatar,
async (req, res) => {
try {
// Update user in database
const user = await User.findByIdAndUpdate(
req.user.id,
{
avatar: req.avatar.optimized,
avatarThumbnail: req.avatar.thumbnail
},
{ new: true }
);
// Delete old avatar files if they exist
if (user.oldAvatar) {
const oldPath = path.join(__dirname, '..', user.oldAvatar);
if (fs.existsSync(oldPath)) fs.unlinkSync(oldPath);
}
res.json({
success: true,
message: 'Profile picture updated successfully',
data: {
avatar: req.avatar.optimized,
thumbnail: req.avatar.thumbnail
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
}
);
// Get user profile with avatar
router.get('/me', authenticate, async (req, res) => {
const user = await User.findById(req.user.id).select('-password');
res.json({
success: true,
data: {
id: user.id,
name: user.name,
email: user.email,
avatar: user.avatar ? `${req.protocol}://${req.get('host')}${user.avatar}` : null,
avatarThumbnail: user.avatarThumbnail ? `${req.protocol}://${req.get('host')}${user.avatarThumbnail}` : null
}
});
});
module.exports = router;11. Common Mistakes + Solutions
Mistake 1: Missing enctype in HTML form
<!-- ❌ File won't upload -->
<form action="/upload" method="POST">
<!-- ✅ Correct enctype -->
<form action="/upload" method="POST" enctype="multipart/form-data">Mistake 2: Wrong field name
// Client side
<input type="file" name="myImage">
// ❌ Wrong field name in multer
upload.single('image')
// ✅ Correct field name
upload.single('myImage')Mistake 3: Not creating upload directory
// ❌ Error: ENOENT: no such file or directory
const upload = multer({ dest: 'uploads/' });
// ✅ Create directory first
const fs = require('fs');
if (!fs.existsSync('uploads')) {
fs.mkdirSync('uploads');
}Mistake 4: Forgetting to handle file size error
// ❌ User gets cryptic error
const upload = multer({ dest: 'uploads/' });
// ✅ Handle multer errors
upload.single('file')(req, res, (err) => {
if (err instanceof multer.MulterError) {
if (err.code === 'FILE_TOO_LARGE') {
return res.status(400).json({ error: 'File too large!' });
}
}
});Mistake 5: Not validating file type
// ❌ Any file can be uploaded
const upload = multer({ dest: 'uploads/' });
// ✅ Validate file type
const fileFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image/')) {
cb(null, true);
} else {
cb(new Error('Only images allowed'), false);
}
};12. Quick Cheat Sheet
Installation:
npm install multerBasic Setup:
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });Single File:
upload.single('fieldname')
// Access: req.fileMultiple Files (same field):
upload.array('fieldname', maxCount)
// Access: req.files (array)Multiple Files (different fields):
upload.fields([
{ name: 'avatar', maxCount: 1 },
{ name: 'gallery', maxCount: 5 }
])
// Access: req.files.avatar, req.files.galleryDisk Storage:
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => cb(null, Date.now() + '-' + file.originalname)
});File Filter:
const fileFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image/')) {
cb(null, true);
} else {
cb(new Error('Only images!'), false);
}
};Limits:
limits: {
fileSize: 5 * 1024 * 1024, // 5MB
files: 5,
fields: 10
}13. FAQ
Q1: Express file upload Multer Hindi में सबसे important concept kya hai?upload.single() – ye single file upload handle करता है। File req.file में आती है।
Q2: Multer kya hai?
Multer Node.js middleware hai jo multipart/form-data (file uploads) handle करता है।
Q3: diskStorage vs memoryStorage – kya use karein?
DiskStorage – files save karne के लिए (profile pictures, documents)। MemoryStorage – cloud upload या image processing के लिए (buffer में चाहिए)।
Q4: File size limit kaise set karein?limits: { fileSize: 5 * 1024 * 1024 } – 5MB limit।
Q5: File type validation kaise karein?fileFilter function use करो – mimetype check करो।
Q6: Multiple files upload kaise karein?upload.array('files', 5) – same field name से multiple files।
Q7: Different fields से files kaise upload karein?upload.fields([{ name: 'avatar' }, { name: 'resume' }])
Q8: Uploaded files serve kaise karein?app.use('/uploads', express.static('uploads'))
Q9: Image compress/resize kaise karein?sharp library use करो – upload के बाद process करो।
Q10: Multer errors handle kaise karein?upload.single()(req, res, (err) => {}) – callback में error handle करो।
14. Conclusion
बहुत बढ़िया दोस्तों! आज हमने Express file upload Multer Hindi को पूरी detail में समझा।
Quick Recap:
| Concept | Key Takeaway |
|---|---|
| Multer | File upload middleware |
| Single File | upload.single('field') |
| Multiple Files | upload.array() or upload.fields() |
| Validation | fileFilter for type, limits for size |
| Storage | DiskStorage (save) vs MemoryStorage (buffer) |
| Processing | Sharp for image resize/compress |
Mera personal experience:
File upload pehle complex lagta था – raw Node.js में बहुत code likhna padta था। Multer ने सब easy कर दिया। अब 5 lines में file upload working है। Image processing ke liye Sharp use करो – quality maintain रहती है।
Tum bhi ye steps follow karo:
- ✅ Multer install करो
- ✅ Basic single file upload implement करो
- ✅ File validation add करो (type, size)
- ✅ Multiple files upload try करो
- ✅ Sharp से image processing add करो
अब तुम्हारी बारी है!
नीचे comment में बताओ:
- तुमने कभी file upload implement kiya है?
- कौन सा validation sabse important लगा?
- अगला topic क्या चाहिए? (MongoDB with Mongoose? JWT Authentication? WebSockets?)
The Easy Master पर बने रहो। Happy File Uploading! 🚀📁
Resources
Additional Resources
- React.js Kya Hai? JSX aur Components Samjhe – Beginner Guide 2026
- React Props and State Data Flow Hindi – समझे आसान भाषा में 2026
- React Router v6 – Multi-Page App Banaye (Routing Guide) 2026
- Advanced React Hooks – useContext and useReducer Samjhe 2026
- Redux Toolkit Simplified – State Management Aasaan Tarika 2026
- React API Integration Made Easy with Fetch and Axios
- React Performance Optimization – App Ko Fast कैसे बनाएं 2026
- React 19 New Features – AI Integration with React (2026)
- Node.js क्या है? 2026 में अपना पहला Backend Server बनाएँ
- NPM Packages कैसे इंस्टॉल करें? Modules (ESM vs CommonJS) 2026
- Express.js Tutorial – REST API Routing और Middleware समझे 2026
- Prisma ORM MongoDB से Database Connect कैसे करें – Easy Tutorial Hindi
- JWT Authentication Node.js – Secure Login System बनाए 2026
- WebSockets Node.js – Live Chat App कैसे बनाएं (Socket.io)
- Async Await vs Promises – Node.js में Async Code कैसे सीखें?
- Microservices Architecture node.js आसान हिंदी Explanation 2026
- Docker से Node.js App Production Ready Deploy करें 2026
- Express.js Setup – पहला Server कैसे बनाएं (Step-by-Step) 2026
- Express.js Routing – GET POST PUT DELETE Complete Guide
- Express Middleware समझे – Application, Router, Error Middleware
- Express req and res Objects – Query, Params, Body, Headers Explained
- Express Static Files और Templating – EJS से Dynamic HTML Banaye
- Express Router – API Routes को Organize करें (Modular Code)
- Express.js में Environment Variables – .env File कैसे Use करें