File Upload

Conform support validating a file input as well.

Configuration

Setting up a file input is similar to other form controls except the form encType attribute must be set to multipart/form-data.

1import { useForm } from '@conform-to/react';
2import { parse } from '@conform-to/zod';
3import { z } from 'zod';
4
5const schema = z.object({
6  profile: z.instanceof(File, { message: 'Profile is required' }),
7});
8
9function Example() {
10  const [form, { profile }] = useForm({
11    onValidate({ formData }) {
12      return parse(formData, { schema });
13    },
14  });
15
16  return (
17    <form encType="multipart/form-data" {...form.props}>
18      <div>
19        <label>Profile</label>
20        <input type="file" name={profile.name} />
21        <div>{profile.error}</div>
22      </div>
23      <button>Upload</button>
24    </form>
25  );
26}
27

Multiple files

The setup is no different for multiple files input.

1import { useForm } from '@conform-to/react';
2import { parse } from '@conform-to/zod';
3import { z } from 'zod';
4
5const schema = z.object({
6  files: z
7    .array(
8      z
9        .instanceof(File)
10        // Don't validate individual file. The error below will be ignored.
11        .refine((file) => file.size < 1024, 'File size must be less than 1kb'),
12    )
13    .min(1, 'At least 1 file is required')
14    // Instead, please validate it on the array level
15    .refine(
16      (files) => files.every((file) => file.size < 1024),
17      'File size must be less than 1kb',
18    ),
19});
20
21function Example() {
22  const [form, { files }] = useForm({
23    onValidate({ formData }) {
24      return parse(formData, { schema });
25    },
26  });
27
28  return (
29    <form encType="multipart/form-data" {...form.props}>
30      <div>
31        <label>Mutliple Files</label>
32        <input type="file" name={files.name} multiple />
33        <div>{files.error}</div>
34      </div>
35      <button>Upload</button>
36    </form>
37  );
38}
39