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.

upload.controller.ts
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:

Validating non-file fields
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:

Disk storage
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, ...).

Validation
WebSockets