Formidable is a powerful Node.js module for parsing form data, especially file uploads. This cheatsheet provides an extensive overview of Formidable's features, usage, and best practices.
Install Formidable using npm:
npm install formidable
Here's a simple example of using Formidable in a Node.js application:
const http = require('http');
const formidable = require('formidable');
http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// Parse a file upload
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
});
return;
}
// Show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
}).listen(8080);
Formidable supports various options for parsing:
const form = formidable({
multiples: true,
uploadDir: '/tmp',
keepExtensions: true,
maxFileSize: 200 * 1024 * 1024, // 200MB
filter: function ({ name, originalFilename, mimetype }) {
// keep only images
return mimetype && mimetype.includes("image");
}
});
Handle file uploads easily:
const form = formidable({ uploadDir: '/tmp', keepExtensions: true });
form.parse(req, (err, fields, files) => {
if (err) {
console.error('Error', err);
throw err;
}
console.log('Fields', fields);
console.log('Files', files);
});
Work with multiple file uploads:
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
console.error('Error', err);
throw err;
}
if (Array.isArray(files.upload)) {
// Multiple files
files.upload.forEach(file => {
console.log('Uploaded file:', file.originalFilename);
});
} else {
// Single file
console.log('Uploaded file:', files.upload.originalFilename);
}
});
Customize uploaded file names:
const form = formidable({
uploadDir: '/tmp',
keepExtensions: true,
filename: (name, ext, part, form) => {
return 'file_' + part.originalFilename;
}
});
Track upload progress:
form.on('progress', (bytesReceived, bytesExpected) => {
const percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write(`
Progress: ${percent}%`);
});
Handle errors during parsing:
form.parse(req, (err, fields, files) => {
if (err) {
if (err.code === 'ETOOBIG') {
console.error('File size limit exceeded');
} else {
console.error('Parsing error:', err);
}
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
// Process fields and files
});
Access form fields:
form.parse(req, (err, fields, files) => {
if (err) throw err;
console.log('Username:', fields.username);
console.log('Email:', fields.email);
});
Parse JSON data:
const form = formidable({ encoding: 'utf-8', multiples: true });
form.parse(req, (err, fields, files) => {
if (err) throw err;
if (req.headers['content-type'] === 'application/json') {
const jsonData = JSON.parse(fields.data);
console.log('Parsed JSON:', jsonData);
}
});
Integrate Formidable with Express:
const express = require('express');
const formidable = require('formidable');
const app = express();
app.post('/upload', (req, res, next) => {
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
app.listen(3000, () => console.log('Server started on port 3000'));
Stream uploaded files:
const fs = require('fs');
form.onPart = (part) => {
if (part.filename) {
// Stream to file
const writeStream = fs.createWriteStream(`/tmp/${part.filename}`);
part.pipe(writeStream);
} else {
// Handle non-file parts
form.handlePart(part);
}
};
Implement security measures:
const form = formidable({
uploadDir: '/tmp',
maxFileSize: 50 * 1024 * 1024, // 50MB
filter: function ({ name, originalFilename, mimetype }) {
// Allow only specific file types
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
return allowedTypes.includes(mimetype);
}
});
Test file uploads using supertest:
const request = require('supertest');
const app = require('./app'); // Your Express app
describe('File Upload', () => {
it('should upload a file', async () => {
const response = await request(app)
.post('/upload')
.attach('file', 'test/fixtures/test-file.txt')
.field('name', 'Test File');
expect(response.status).toBe(200);
expect(response.body.files.file).toBeDefined();
expect(response.body.fields.name).toBe('Test File');
});
});
2024 © All rights reserved - buraxta.com