Skip to content

ExpressJS - Form Data

Express.js - Handling Form Data and File Uploads

Section titled “Express.js - Handling Form Data and File Uploads”

Handling incoming data from clients—whether from an HTML form, a JSON API request, or a file upload—is a fundamental task for any web server. Express provides built-in middleware for common data formats and relies on libraries like Multer for more complex cases like file uploads.

Parsing Request Bodies with Built-in Middleware

Section titled “Parsing Request Bodies with Built-in Middleware”

In modern versions of Express (4.16.0+), the middleware required to parse JSON and URL-encoded bodies is now included directly within the Express package. You no longer need to install the body-parser package separately.

import express from 'express';
const app = express();
// 1. Middleware for parsing JSON bodies
// This is used for API requests, e.g., from a frontend framework.
app.use(express.json());
// 2. Middleware for parsing URL-encoded bodies
// This is used for traditional HTML form submissions.
app.use(express.urlencoded({ extended: true }));
// Your routes will now have access to a populated `req.body` object.
app.post('/api/users', (req, res) => {
console.log('Received data:', req.body);
const { username, email } = req.body;
// Validate and process the data...
if (!username || !email) {
return res.status(400).json({ message: 'Username and email are required.' });
}
res.status(201).json({ message: 'User created successfully!', user: req.body });
});
app.listen(3000, () => console.log('Server running on port 3000'));

You can test the above endpoint using a tool like curl:

# Testing the JSON endpoint
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"username":"john_doe","email":"john.doe@example.com"}'
# Testing the URL-encoded endpoint
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'username=jane_doe&email=jane.doe@example.com'

For handling multipart/form-data, which is primarily used for uploading files, the standard library is Multer. It’s a powerful middleware that adds file or files objects to your request object.

# Install multer
npm install multer

Here is a complete example of setting up a route to handle a single file upload and save it to the server.

import express from 'express';
import multer from 'multer';
import path from 'path';
const app = express();
// Configure Multer storage
const storage = multer.diskStorage({
destination: function (req, file, cb) {
// The destination directory for uploads
cb(null, './uploads/');
},
filename: function (req, file, cb) {
// Create a unique filename to avoid overwrites
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
});
// Initialize multer with the storage configuration
const upload = multer({ storage: storage });
// Make the 'uploads' directory publicly accessible if you want to serve the files
app.use('/uploads', express.static('uploads'));
// The route for handling the file upload
// 'profileImage' is the name of the form field (<input type="file" name="profileImage">)
app.post('/api/upload-profile-picture', upload.single('profileImage'), (req, res) => {
if (!req.file) {
return res.status(400).send('No file uploaded.');
}
// req.file contains information about the uploaded file
console.log('File uploaded:', req.file);
res.status(200).json({
message: 'File uploaded successfully!',
filename: req.file.filename,
path: req.file.path
});
});
app.listen(3000, () => console.log('Server running on port 3000'));
  • Always Validate Input: Never trust user-submitted data. Use a library like express-validator or joi to validate and sanitize req.body and req.params before processing them. This helps prevent NoSQL injection, XSS, and other vulnerabilities.
  • File Upload Security: When accepting file uploads, be extremely cautious. Configure Multer with file filters to only allow specific file types (e.g., image/jpeg, image/png) and set limits on file sizes to prevent denial-of-service attacks.
  • Use express.Router: For better organization, group related routes into separate files using express.Router instead of putting all routes in your main application file.