1. Update the uploadHelper.js
to include a size check within the middleware configuration:
const path = require('path');
const fs = require('fs');
// 1. Helper method: File size limit
const limitFileSize = (maxSize) => {
return {
fileSize: maxSize
};
};
// 2. Helper method: File type filter
const fileFilter = (allowedTypes) => (req, file, cb) => {
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
return cb(new Error('File type is not allowed.'));
}
};
// 3. Helper method: Ensure directory exists
const ensureDirExists = (dir) => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
};
// 4. Helper method: Generate unique file name
const generateFileName = (req, file, cb) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
cb(null, file.fieldname + '-' + uniqueSuffix + ext);
};
// 5. Helper method: Destination directory
const destination = (req, file, cb) => {
cb(null, path.join(__dirname, '../uploads/'));
};
// Export the helper methods
module.exports = {
limitFileSize,
fileFilter,
ensureDirExists,
generateFileName,
destination,
};
Update the multer
Configuration to Use limitFileSize
:
uploadMiddleware.js
:
const multer = require('multer');
const { destination, generateFileName, limitFileSize, fileFilter } = require('./uploadHelper');
// Create a storage configuration using helper methods
const storage = multer.diskStorage({
destination: destination, // Use the helper method to set the destination directory
filename: generateFileName, // Use the helper method to generate the file name
});
// Use the `limitFileSize` helper to set the file size limit (e.g., 5 MB)
const upload = multer({
storage: storage, // Use the custom storage configuration
limits: limitFileSize(5 * 1024 * 1024), // Set the file size limit using the helper method
fileFilter: fileFilter(/jpeg|jpg|png|gif/), // Allow specific file types
});
module.exports = upload;
Use the Middleware in Routes:
index.js
:
const express = require('express');
const upload = require('./uploadMiddleware'); // Import the multer configuration
const app = express();
const port = 3000;
// Route: Single file upload
app.post('/upload-single', upload.single('singleFile'), (req, res) => {
res.status(200).json({
message: 'File uploaded successfully!',
file: req.file, // Information about the uploaded file
});
});
// Route: Multiple file upload
app.post('/upload-multiple', upload.array('multipleFiles', 5), (req, res) => {
res.status(200).json({
message: 'Files uploaded successfully!',
files: req.files, // Information about the uploaded files
});
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Some add Feature
Step 1: Create Helper Methods
uploadHelper.js
:
const path = require('path');
const fs = require('fs');
// 1. Helper Method: File Size Limit
const limitFileSize = (maxSize) => {
return {
fileSize: maxSize,
};
};
// 2. Helper Method: File Type Filter
const fileFilter = (allowedTypes) => (req, file, cb) => {
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
return cb(new Error('Only specified file types are allowed!'));
}
};
// 3. Helper Method: Ensure Directory Exists
const ensureDirExists = (dir) => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
};
// 4. Helper Method: Generate Unique File Name
const generateFileName = (req, file, cb) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
cb(null, file.fieldname + '-' + uniqueSuffix + ext);
};
// 5. Helper Method: Set Destination Directory
const destination = (dir) => (req, file, cb) => {
ensureDirExists(dir); // Ensure the directory exists before saving files
cb(null, dir);
};
// 6. Helper Method: Sanitize File Name
const sanitizeFileName = (fileName) => {
return fileName.replace(/[^a-z0-9\.-]/gi, '_').toLowerCase();
};
// 7. Helper Method: Delete File (for cleanup)
const deleteFile = (filePath) => {
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
};
// 8. Helper Method: Validate File Count
const limitNumberOfFiles = (maxFiles) => (req, res, next) => {
if (req.files && req.files.length > maxFiles) {
return res.status(400).json({ error: `You can upload a maximum of ${maxFiles} files.` });
}
next();
};
// Export the helper methods
module.exports = {
limitFileSize,
fileFilter,
ensureDirExists,
generateFileName,
destination,
sanitizeFileName,
deleteFile,
limitNumberOfFiles,
};
Step 2: Configure Multer with Advanced Options
uploadMiddleware.js
:
const multer = require('multer');
const path = require('path');
const {
destination,
generateFileName,
limitFileSize,
fileFilter,
sanitizeFileName,
} = require('./uploadHelper');
// Directory where files will be uploaded
const uploadDirectory = path.join(__dirname, '../uploads');
// Configure storage
const storage = multer.diskStorage({
destination: destination(uploadDirectory), // Use the helper method to set the destination
filename: (req, file, cb) => {
const sanitizedFileName = sanitizeFileName(file.originalname);
const ext = path.extname(sanitizedFileName);
const baseName = path.basename(sanitizedFileName, ext);
cb(null, `${baseName}-${Date.now()}${ext}`);
},
});
// Configure Multer with advanced options
const upload = multer({
storage: storage,
limits: limitFileSize(5 * 1024 * 1024), // Limit file size to 5MB
fileFilter: fileFilter(/jpeg|jpg|png|gif|pdf|docx/), // Allow specific file types
});
module.exports = upload;
Implement the Upload Routes
index.js
:
const express = require('express');
const upload = require('./uploadMiddleware');
const { limitNumberOfFiles } = require('./uploadHelper');
const app = express();
const port = 3000;
// Route: Single file upload
app.post('/upload-single', upload.single('singleFile'), (req, res) => {
res.status(200).json({
message: 'File uploaded successfully!',
file: req.file,
});
});
// Route: Multiple file upload with a limit of 5 files
app.post('/upload-multiple', upload.array('multipleFiles', 10), limitNumberOfFiles(5), (req, res) => {
res.status(200).json({
message: 'Files uploaded successfully!',
files: req.files,
});
});
// Route: Upload with memory storage
app.post('/upload-single-memory', multer({ storage: multer.memoryStorage() }).single('singleFile'), (req, res) => {
const fileBuffer = req.file.buffer;
res.status(200).json({
message: 'File uploaded successfully and stored in memory!',
file: req.file,
});
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Explanation:
limitFileSize
: Limits the size of each uploaded file to 5MB.fileFilter
: Ensures only files with specific MIME types (e.g., images and documents) are allowed.ensureDirExists
: Automatically creates the upload directory if it doesn’t exist.generateFileName
: Generates a unique filename to prevent overwriting.sanitizeFileName
: Removes any potentially dangerous or special characters from the file name.deleteFile
: Provides a utility to delete files when necessary (e.g., when replacing a file).limitNumberOfFiles
: Limits the number of files that can be uploaded in a single request.
Step 4: Test the Implementation
You can now start the server and test the file upload functionality by sending POST requests to the following endpoints:
/upload-single
: Upload a single file./upload-multiple
: Upload multiple files (with a limit of 5 files)./upload-single-memory
: Upload a single file and store it in memory.
This setup provides a robust, secure, and flexible local upload system using Multer
and helper methods to handle common file upload tasks.