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