Skip to content

upload / fields — file upload middleware (Express only) ​

Express engine only. On Hono, use c.req.parseBody() instead. See Upload guide.

Imported from the facade: import { upload, fields } from "@/framework/facade.js".

Parser factories for multipart/form-data requests. They wrap multer (memory storage) so controllers receive ready-to-use buffers (req.file / req.files) with size/extension/MIME rules already enforced.

Functions ​

FunctionSignatureDescription
upload(options: UploadOptions) => RequestHandlerParse a single file (or up to multiple files) from one form field into req.file / req.files
fields(spec: UploadFieldsSpec, options?) => RequestHandlerParse multiple labeled file fields into req.files (object keyed by field name)

UploadOptions ​

OptionTypeDescription
fieldstringForm field name that carries the file(s)
multiplenumberAccept an array of up to N files on the field
maxSizenumberMax allowed file size in bytes (default unlimited)
allowedExtensionsstring[]Lowercase extensions with dot, e.g. [".xlsx"]
allowedMimeTypesstring[]Allowed MIME types; both extension and MIME type must be allowed

UploadFieldsSpec ​

FieldTypeDescription
namestringForm field name
maxCountnumberMax files for one labeled field

UploadFieldsOptions ​

OptionTypeDescription
maxSizenumberMax allowed file size in bytes (default unlimited)
allowedExtensionsstring[]Lowercase extensions with dot, e.g. [".xlsx"]
allowedMimeTypesstring[]Allowed MIME types; both extension and MIME type must be allowed

Use cases ​

Route-level enforcement ​

Enforce rules before the controller runs by passing the middleware into .api():

ts
import { createRoute, group, z, upload } from "@/framework/facade.js";
import type { Request, Response } from "express";

export default group().api(
  uploadRoute,
  [
    upload({
      field: "file",
      maxSize: 2 * 1024 * 1024,
      allowedExtensions: [".jpg", ".png"],
    }),
  ],
  (req: Request, res: Response) => {
    res.json(req.file);
  },
);

Combined with other middleware ​

upload() composes with auth/role middleware like any other RequestHandler:

ts
export default group().api(
  avatarRoute,
  [requireRole("user"), upload({ field: "avatar" })],
  storeAvatar,
);

Failure shape ​

Failures surface as 422 before the controller runs, so handlers never receive a missing/wrong file:

ts
// error.status === 422
// error.message === "File size must be less than 2 MB"
// error.message === "File must be .jpg or .png"
// error.message === "File type image/gif is not allowed"
// error.message === "Too many files, max 3 allowed"
// error.message === "File required"

Notes ​

  • Memory storage only — buffers live in req.file / req.files; persist with storage.putFile etc. (see Storage > Multipart File Upload).
  • Express-only export: importing from a Hono project fails at type-check; Hono apps parse bodies via c.req.parseBody().

Released under the MIT License.