File Plugin
Handles multipart/form-data file uploads with comprehensive security features. Automatically parses uploaded files, validates them, sanitizes filenames, and provides access through req.files and req.file.
Quick Start
import { Server } from 'balda-js';
const server = new Server({
plugins: {
file: {
maxFileSize: '5mb'
}
}
});
Configuration
All options are optional. Defaults: maxFileSize: "1mb", maxFiles: 10, allowedMimeTypes: [] (all types).
maxFileSize
Maximum size for each uploaded file:
file: {
maxFileSize: '5mb' // 5 megabytes (default: 1mb)
}
file: {
maxFileSize: '500kb' // 500 kilobytes
}
maxFiles
Maximum number of files per request:
file: {
maxFiles: 3 // Default: 10
}
allowedMimeTypes
Whitelist of allowed MIME types:
file: {
allowedMimeTypes: [
'image/jpeg',
'image/png',
'image/gif',
'application/pdf'
]
}
// Empty array (default) allows all MIME types
file: {
allowedMimeTypes: []
}
Usage
Single File Upload
@controller('/api')
export class UploadController {
@post('/upload')
async uploadFile(req: Request, res: Response) {
const file = req.file; // Single file
if (!file) {
return res.badRequest({ error: 'No file uploaded' });
}
res.json({
filename: file.filename,
originalFilename: file.originalFilename,
size: file.size,
mimeType: file.mimeType,
path: file.path
});
}
}
Multiple Files Upload
@post('/upload/multiple')
async uploadMultiple(req: Request, res: Response) {
const files = req.files; // Array of files
if (!files || files.length === 0) {
return res.badRequest({ error: 'No files uploaded' });
}
const fileInfos = files.map(f => ({
filename: f.filename,
size: f.size,
mimeType: f.mimeType
}));
res.json({ files: fileInfos });
}
HTML Form Example
<form action="/api/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit">Upload</button>
</form>
<!-- Multiple files -->
<form action="/api/upload/multiple" method="POST" enctype="multipart/form-data">
<input type="file" name="files" multiple />
<button type="submit">Upload Files</button>
</form>
File Object
Each file object contains:
{
filename: string; // Sanitized filename (e.g., "avatar.png")
originalFilename: string; // Original uploaded filename
path: string; // Temporary file path
size: number; // File size in bytes
mimeType: string; // MIME type (e.g., "image/png")
}
Security Features
Filename Sanitization
Automatically removes:
- Path traversal (
../) - Directory separators (
/,\) - Null bytes
- Control characters
// Input: "../../../etc/passwd"
// Sanitized: "etcpasswd"
// Input: "file\x00.txt"
// Sanitized: "file.txt"
Cryptographically Secure Temporary Files
Temporary files use UUID-based filenames to prevent:
- Filename collisions
- Predictable paths
- Overwriting attacks
Automatic Cleanup
Temporary files are automatically deleted after request completion, even if errors occur.
Error Responses
File Too Large
// Response: 413 Payload Too Large
{
"error": "File size exceeds limit"
}
Too Many Files
// Response: 400 Bad Request
{
"error": "Too many files. Maximum 10 allowed"
}
Invalid MIME Type
// Response: 400 Bad Request
{
"error": "Invalid file type. Allowed: image/jpeg, image/png"
}
Missing Content-Type
// Response: 400 Bad Request
{
"error": "Content-Type must be multipart/form-data"
}
Complete Example
const server = new Server({
plugins: {
file: {
maxFileSize: '10mb',
maxFiles: 5,
allowedMimeTypes: [
'image/jpeg',
'image/png',
'image/gif',
'application/pdf'
]
}
}
});
@controller('/api')
export class FileController {
@post('/upload')
async handleUpload(req: Request, res: Response) {
const file = req.file;
if (!file) {
return res.badRequest({ error: 'No file provided' });
}
// Process file (e.g., move to permanent storage)
await moveFile(file.path, `uploads/${file.filename}`);
res.json({
success: true,
filename: file.filename,
size: file.size
});
}
}
Common Patterns
Image Upload with Validation
file: {
maxFileSize: '5mb',
maxFiles: 1,
allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp']
}
Document Upload
file: {
maxFileSize: '10mb',
maxFiles: 3,
allowedMimeTypes: [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
]
}
Profile Picture Upload
file: {
maxFileSize: '2mb',
maxFiles: 1,
allowedMimeTypes: ['image/jpeg', 'image/png']
}
Performance Tips
- Set reasonable
maxFileSizelimits - Use
allowedMimeTypesto prevent unwanted files - Store files in object storage (S3, etc.) for production
- Consider using streaming for very large files
- Validate file contents, not just MIME types