CORE CONCEPTS
fileUpload() Middleware
fileUpload() provides Multer-style multipart handling on top of the Web Standard request.formData() API. If you've used Multer with Express, the API will feel immediately familiar.
Basic Usage
import { fileUpload } from '@rasenganjs/futon'; const upload = fileUpload({ limits: { fileSize: 5 * 1024 * 1024 } }); // 5 MB router.post('/avatar', upload.single('avatar'), async (ctx) => { const file = ctx.get('file'); // UploadedFile return json({ size: file.size, name: file.originalname }); });
The Uploader Methods
fileUpload(options) returns an Uploader with five methods, each producing a Middleware:
const upload = fileUpload(); router.post( '/gallery', upload.fields([ { name: 'cover', maxCount: 1 }, { name: 'photos', maxCount: 10 }, ]), async (ctx) => { const { cover, photos } = ctx.get('files'); return json({ cover: cover?.[0]?.originalname, count: photos?.length }); } );
Non-file fields in the same multipart body become ctx.body — just like Multer's req.body.
UploadOptions
const upload = fileUpload({ fileFilter: (ctx, info) => info.mimetype.startsWith('image/'), });
Unlike Multer, a rejected file produces an explicit 400 FILE_FILTER_REJECTED response rather than silently skipping the file.
Error Responses
Every rejection returns JSON with an error code you can match on:
{ "error": { "code": "LIMIT_FILE_SIZE", "message": "File \"photo.png\" exceeds the 5242880 byte limit." } }
Validation Order and Rollback
Every part of the multipart body is validated before anything is stored — limits, unexpected fields, and fileFilter are all checked first. If a file fails to store partway through a multi-file batch, already-stored files are rolled back via the storage engine's removeFile().
If bodyParser() already ran and parsed the multipart body into ctx.state.body as a FormData, fileUpload() reuses it instead of re-reading the request — a Request body can only be consumed once. Pass { skipMultipart: true } to bodyParser() if you'd rather it leave multipart bodies untouched for fileUpload() to parse.
