Uploading files in an Express.js application using EJS and Mongoose
Uploading files in an Express.js application using EJS and Mongoose involves setting up file upload functionality, handling file storage, and integrating it with your application’s data model. Here’s a step-by-step guide to implementing file uploads:
1. Set Up Your Project
Initialize the Project:
If you haven't already, initialize your project and install necessary dependencies:
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 the Basic Structure:
Create the following 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 the 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 for File Uploads
Multer is used to handle file uploads. Configure it to store files in a specific directory.
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
}
});
const upload = multer({ storage: storage });
// 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 {
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'));
// 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. - After uploading, you should be redirected to the homepage where you can see the list of uploaded files.
- Go to
View Uploaded Files:
- Click the “View File” link next to an item to view the uploaded file.
Summary
- Project Setup: Initialize the project, install dependencies, and configure Express, Mongoose, and Multer.
- Mongoose Model: Define a model to store file metadata in MongoDB.
- Multer Configuration: Set up Multer for handling file uploads and storing files in a directory.
- EJS Templates: Create templates for displaying the file upload form and the list of uploaded files.
- Testing: Verify the file upload functionality by uploading and viewing files.
This setup provides a basic implementation of file uploading using Express.js, EJS, and Mongoose. You can further enhance it with features like file validation, error handling, and more.