Upload file with File Size and Type Validation in express JS and MongoDB
When handling file uploads in an Express.js application, it’s important to validate the file size and type to ensure that users only upload files that are acceptable for your application. This validation helps protect your application from potential security risks and ensures that only files of a specific type and size are processed.
Here’s how to implement file size and type validation using multer
in an Express.js application with MongoDB:
1. Set Up Your Project
Initialize Your Project:
If you haven't already, set up your project and install the necessary packages:
mkdir express-file-upload cd express-file-upload npm init -y npm install express mongoose ejs multer
express
: Web framework for Node.js.mongoose
: ODM for MongoDB.ejs
: Templating engine.multer
: Middleware for handling file uploads.
Create Basic File Structure:
express-file-upload/ ├── models/ │ └── Item.js ├── views/ │ ├── index.ejs │ └── upload.ejs ├── app.js └── uploads/ (This directory will store uploaded files)
2. Define the Mongoose Model
Create a model to store information about uploaded files.
models/Item.js
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
name: { type: String, required: true },
description: String,
filePath: String // Path to the uploaded file
});
const Item = mongoose.model('Item', itemSchema);
module.exports = Item;
3. Configure Multer with Validation
Multer allows you to set limits and filter file types. You can configure it to handle file size and type validation.
app.js
const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const multer = require('multer');
const bodyParser = require('body-parser');
const Item = require('./models/Item');
const app = express();
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/file-upload', {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Connected to MongoDB');
}).catch(err => {
console.error('Failed to connect to MongoDB', err);
});
// Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
// Set EJS as the view engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Configure Multer
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // Directory to save files
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname)); // Unique filename
}
});
// File filter for type validation
const fileFilter = (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true); // Accept the file
} else {
cb(new Error('Invalid file type. Only JPEG, PNG, and PDF are allowed.'), false); // Reject the file
}
};
// File size limit (e.g., 2 MB)
const limits = { fileSize: 2 * 1024 * 1024 };
const upload = multer({ storage: storage, fileFilter: fileFilter, limits: limits });
// Routes
app.get('/', async (req, res) => {
try {
const items = await Item.find();
res.render('index', { items });
} catch (err) {
console.error(err);
res.status(500).send('Server Error');
}
});
app.get('/upload', (req, res) => {
res.render('upload');
});
app.post('/upload', upload.single('file'), async (req, res) => {
try {
// Handle validation errors
if (req.fileValidationError) {
return res.status(400).send(req.fileValidationError);
}
if (!req.file) {
return res.status(400).send('No file was uploaded.');
}
const newItem = new Item({
name: req.body.name,
description: req.body.description,
filePath: req.file.path // Save file path in the database
});
await newItem.save();
res.redirect('/');
} catch (err) {
console.error(err);
res.status(500).send('Server Error');
}
});
// Static files (for serving uploaded files)
app.use('/uploads', express.static('uploads'));
// Error handling middleware
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
// Multer-specific errors
res.status(500).send(err.message);
} else if (err) {
// Other errors
res.status(500).send(err.message);
}
});
// Start the server
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
4. Create EJS Templates
Create
views/index.ejs
:This template displays a list of uploaded files and their details.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Uploaded Files</title> </head> <body> <h1>Uploaded Files</h1> <a href="/upload">Upload New File</a> <ul> <% items.forEach(item => { %> <li> <strong><%= item.name %></strong>: <%= item.description %> <br> <a href="/uploads/<%= path.basename(item.filePath) %>">View File</a> </li> <% }) %> </ul> </body> </html>
Create
views/upload.ejs
:This template provides a form for uploading new files.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Upload File</title> </head> <body> <h1>Upload New File</h1> <form action="/upload" method="POST" enctype="multipart/form-data"> <label for="name">Name:</label> <input type="text" id="name" name="name" required> <br> <label for="description">Description:</label> <textarea id="description" name="description"></textarea> <br> <label for="file">File:</label> <input type="file" id="file" name="file" required> <br> <button type="submit">Upload File</button> </form> <a href="/">Back to List</a> </body> </html>
5. Test the File Upload
Start the Server:
Run your application:
node app.js
Upload a File:
- Go to
http://localhost:3000/upload
and use the form to upload a file. - The server will validate the file size and type based on the Multer configuration.
- Go to
Error Handling:
- If a file is not of an allowed type or exceeds the size limit, an appropriate error message will be shown.
- Check the
uploads
directory and MongoDB database to ensure the file and its metadata are correctly saved.
Summary
- Project Setup: Initialize your project and install dependencies.
- Mongoose Model: Define a model to store file metadata.
- Multer Configuration: Configure Multer for file size and type validation.
- EJS Templates: Create templates for displaying and uploading files.
- Testing: Verify that file uploads are validated and handled correctly.