JAVASCRIPT
Secure Server-Side File Upload Validation
Implement crucial server-side validation for file uploads in Node.js, checking file type, size, and potential threats to prevent malicious content from being processed by your application.
const express = require('express');
const multer = require('multer'); // Middleware for handling multipart/form-data
const path = require('path');
const fs = require('fs');
const app = express();
const port = 3000;
// Define allowed file types and maximum file size
const allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
const maxFileSize = 5 * 1024 * 1024; // 5 MB
const uploadDir = path.join(__dirname, 'uploads');
// Ensure the upload directory exists
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}
// Configure multer storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, uploadDir); // Files will be stored in the 'uploads' directory
},
filename: (req, file, cb) => {
// Generate a unique filename to prevent overwriting and path traversal attacks
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const fileExtension = path.extname(file.originalname);
cb(null, file.fieldname + '-' + uniqueSuffix + fileExtension);
}
});
// Configure multer upload with file filter and size limit
const upload = multer({
storage: storage,
limits: { fileSize: maxFileSize },
fileFilter: (req, file, cb) => {
// Validate file type
if (!allowedMimeTypes.includes(file.mimetype)) {
return cb(new Error('Invalid file type. Only JPEG, PNG, and PDF are allowed.'), false);
}
cb(null, true); // Accept the file
}
});
// File upload endpoint
app.post('/upload', upload.single('document'), (req, res) => {
if (req.file) {
console.log('File uploaded:', req.file);
res.status(200).send({
message: 'File uploaded successfully!',
filename: req.file.filename,
size: req.file.size,
mimetype: req.file.mimetype
});
} else {
res.status(400).send({ message: 'No file uploaded or file upload failed.' });
}
});
// Error handling middleware for multer errors
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(400).send({ message: `File too large. Max size is ${maxFileSize / (1024 * 1024)} MB.` });
}
// Handle other multer errors
return res.status(400).send({ message: `Multer error: ${err.message}` });
} else if (err) {
// Handle custom fileFilter errors or other generic errors
return res.status(400).send({ message: err.message });
}
next();
});
app.get('/', (req, res) => {
res.send(`
<h1>Secure File Upload Example</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="document" accept="image/jpeg,image/png,application/pdf">
<button type="submit">Upload File</button>
</form>
<p>Allowed types: JPEG, PNG, PDF. Max size: 5MB.</p>
`);
});
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
How it works: This Node.js Express snippet demonstrates secure server-side file upload validation using the `multer` middleware. It enforces strict rules by defining allowed MIME types and a maximum file size. The `fileFilter` function explicitly checks the `mimetype` to prevent malicious file types, and the `limits` option restricts file size. Furthermore, `multer`'s `diskStorage` is configured to generate unique filenames, preventing path traversal and file overwriting vulnerabilities, ensuring only valid and safe files are processed and stored.