File uploads (multipart/form-data)
DaloyJS treats multipart/form-data as a first-class request shape. Two helpers, fileField() and multipartObject(), let you describe an upload contract once, get runtime validation (size caps, MIME allowlists, filename matchers), an end-to-end-typed handler, and a correct OpenAPI document with multipart/form-data media type and format: "binary" file fields.
DaloyJS does not buffer file bodies for you: the runtime FormData entry stays a File or Blob, so handlers can stream it (file.stream()) directly to S3, disk, or another upstream.
- 01requestmultipart/form-data bodyFile / Blob entries kept, not buffered
- 02app capsmaxFileBytes · maxFields · maxFiles413 (size) or 400 (counts)
- 03field capsfileField(): size · MIME · magic bytesforged image/png rejected, 422
- 04handlerTyped bodybody.file.stream() to S3 or disk
Quick start
fileField() options
maxBytes: reject files larger than this many bytes.accept: MIME allowlist. Each entry can be exact ("image/png") or a wildcard ("image/*"/"*/*").filename(name): predicate for filename validation, useful for forcing extensions.magicBytes: verify file signatures before the handler receives the upload.truederives known signatures fromacceptfor PNG, JPEG, GIF, WebP, PDF, ZIP, and GZIP; custom signatures support domain-specific formats.rejectScriptableImages: reject SVG, MVG, MSL, PostScript, and EPS payloads that can execute inside renderers such as ImageMagick. This is enabled automatically whenmagicBytesis configured; set it tofalseonly when the renderer is sandboxed.optional: whentrue, acceptundefined/nullvalues without raising.format: OpenAPI hint, defaults to"binary".
Magic-byte verification
MIME types come from the client, so use magicBytes when the route only accepts formats with recognizable signatures. Daloy rejects a forged image/png upload whose bytes are not PNG bytes, and also rejects a file whose sniffed signature disagrees with the declared MIME type.
Strict form fields
By default, multipartObject() validates the fields you declare and ignores extra form fields. Pass { strict: true } to reject undeclared fields and emit additionalProperties: false in OpenAPI.
App-level safety caps
The framework already enforces bodyLimitBytes on every request. For multipart bodies you can layer additional limits via AppOptions.multipart:
These caps are evaluated as soon as the body is parsed, so a request that exceeds them is rejected with 413 Payload Too Large (size) or 400 Bad Request (counts) before the handler runs.
OpenAPI emission
When the request body is built from multipartObject(), the OpenAPI generator emits multipart/form-data as the request body media type. Each fileField becomes { type: "string", format: "binary" } with optional x-accept, x-max-bytes, and x-magic-bytes annotations so codegen tools and humans both see the constraints.
Validation errors
Field-level failures are returned as a standard 422 Unprocessable Content problem+json document with one entry per failing field, same shape as JSON body validation, so clients have a single error path to handle.