CORE CONCEPTS
File Uploads
Rasengan Server re-exports Futon's fileUpload() middleware and MemoryStorage directly from its main entry. There's no separate upload API to learn.
import { Controller, type RouteHandler, type Router, fileUpload, } from '@rasenganjs/server'; const upload = fileUpload({ limits: { fileSize: 5 * 1024 * 1024 } }); export class UploadController extends Controller { routes(router: Router) { router.post('/avatar', upload.single('avatar'), this.uploadAvatar); } uploadAvatar: RouteHandler = async (ctx) => { const file = ctx.get('file'); return ctx.res.json({ size: file.size, name: file.originalname }); }; }
Since fileUpload() returns a Middleware, upload.single(...)/.array(...)/.fields(...) slot straight into the route-level middleware position, the same overload that accepts requireAuth or any other middleware.
Combining with Validation
Text fields alongside the uploaded file become ctx.body. You can validate them the same way as a regular JSON body:
import z from "zod"; routes(router: Router) { router.post( "/avatar", upload.single("avatar"), this.uploadAvatar, { body: z.object({ caption: z.string().optional() }) } ); }
Disk Storage
DiskStorage/diskStorage() is not re-exported from the main @rasenganjs/server entry (same reasoning as Futon: it imports node:fs, which must stay out of WinterCG bundles). Import it from the dedicated subpath:
import { fileUpload } from '@rasenganjs/server'; import { diskStorage } from '@rasenganjs/server/upload/disk'; // or, equivalently: import { diskStorage } from "@rasenganjs/futon/upload/disk"; const upload = fileUpload({ storage: diskStorage({ destination: 'uploads/' }), });
See Storage Engines for the full StorageEngine interface, DiskStorage options, and how to write a custom engine (S3, R2, GCS, ...).
