Skip to Content
Form with Files

Form with Files Example

An example of a form with files using Zod validation . Notice that “portfolio samples” can be uploaded as multiple files as well as a single file, and the validation model for this field has to be defined as a union of z.file() and z.array(z.file()).

Result








Code

src/modules/form/FormZodController.ts
import { z } from 'zod'; import { prefix, post, operation, type VovkOutput } from 'vovk'; import { withZod } from 'vovk-zod'; @prefix('form-zod') export default class FormZodController { @operation({ summary: 'Submit form (Zod)', description: 'Submit form with Zod validation', }) @post('{id}') static submitForm = withZod({ isForm: true, body: z .object({ email: z.email().meta({ description: 'User email' }), resume: z .file() .meta({ description: 'Resume file', examples: ['application/pdf'] }), portfolioSamples: z.union([z.array(z.file()), z.file()]).meta({ description: 'Portfolio samples' }), }) .meta({ description: 'User object' }), params: z.object({ id: z.uuid().meta({ description: 'User ID' }), }), output: z .object({ email: z.email().meta({ description: 'User email' }), resume: z.object({ name: z.string().meta({ description: 'Resume file name', examples: ['resume.pdf'] }), size: z.number().min(0).meta({ description: 'Resume file size' }), type: z.string().meta({ description: 'Resume file type', examples: ['application/pdf'] }), }), portfolioSamples: z .object({ name: z.string().meta({ description: 'Portfolio sample file name', examples: ['portfolio.zip'] }), size: z.number().min(0).meta({ description: 'Portfolio sample file size' }), type: z.string().meta({ description: 'Portfolio sample file type', examples: ['application/zip'] }), }) .array() .meta({ description: 'Array of portfolio sample files' }), }) .meta({ description: 'Response object' }), async handle(req, { id }) { const { resume, portfolioSamples, email } = await req.vovk.form(); return { email, resume: { name: resume.name, size: resume.size, type: resume.type, }, portfolioSamples: (Array.isArray(portfolioSamples) ? portfolioSamples : [portfolioSamples]).map((file) => ({ name: file.name, size: file.size, type: file.type, })), } satisfies VovkOutput<typeof FormZodController.submitForm>; }, }); }

The code above is fetched from GitHub repository. 

Last updated on