JAVASCRIPT
Secure Server-Side File Upload Validation in Node.js
Enhance security for file uploads by implementing strict server-side validation of file types and extensions in Node.js using `multer`.
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// Define allowed MIME types and file extensions
const allowedMimeTypes = [
'image/jpeg',
'image/png',
'application/pdf'
];
const allowedExtensions = [
'.jpg',
'.jpeg',
'.png',
'.pdf'
];
// Configure Multer storage
const storage = multer.memoryStorage(); // Store file in memory to validate before saving
const fileFilter = (req, file, cb) => {
// 1. Check MIME type
if (!allowedMimeTypes.includes(file.mimetype)) {
return cb(new Error('Invalid file type.'), false);
}
// 2. Check file extension
const ext = path.extname(file.originalname).toLowerCase();
if (!allowedExtensions.includes(ext)) {
return cb(new Error('Invalid file extension.'), false);
}
// 3. Optional: More robust content-based type checking (e.g., using 'file-type' library)
// For production, consider reading first few bytes to verify actual file type.
// Example: if (file.mimetype === 'image/jpeg') { check first bytes for JPEG signature }
cb(null, true); // Accept file
};
const upload = multer({
storage: storage,
fileFilter: fileFilter,
limits: {
fileSize: 5 * 1024 * 1024 // 5MB limit
}
});
app.post('/upload', upload.single('document'), (req, res) => {
if (!req.file) {
return res.status(400).json({ message: 'No file uploaded or file type/extension is invalid.' });
}
// In a real application, save the buffer to disk or cloud storage
// Example: fs.writeFileSync(path.join(__dirname, 'uploads', req.file.originalname), req.file.buffer);
console.log(`File uploaded: ${req.file.originalname}, Type: ${req.file.mimetype}, Size: ${req.file.size} bytes`);
res.status(200).json({ message: 'File uploaded successfully!', filename: req.file.originalname });
});
// Error handling middleware for multer
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
return res.status(400).json({ message: err.message });
} else if (err) {
return res.status(400).json({ message: err.message });
}
next();
});
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
How it works: This Node.js snippet demonstrates robust server-side file upload validation using `multer`. It configures a `fileFilter` to strictly check both the file's MIME type and its extension against predefined allowed lists, preventing the upload of potentially malicious or unexpected file formats. Files are stored in memory (`memoryStorage`) during validation before being processed, and a file size limit is also enforced, enhancing overall application security.