Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zod validator / validate image

I have a problem, I need to validate an image with zod. I am searching for 3 hours. I can't find out on validating the image? Can anyone help me out to fix this? zod must have image validate yes?

const payloadSchema = z.object({
    image: z.record(z.string()),
})

Find something like this, but how can I add the image that is 3 mb max and it's type must be "jpg" "png" or "gif"

like image 577
BasDriver Avatar asked Dec 10 '25 17:12

BasDriver


2 Answers

Try this it, it seems simple and it works for me:

const MAX_FILE_SIZE = 5000000;
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png", "image/webp"];

const someSchema = z.object({
  image: z
    .any()
    .refine((file) => file?.size <= MAX_FILE_SIZE, `Max image size is 5MB.`)
    .refine(
      (file) => ACCEPTED_IMAGE_TYPES.includes(file?.type),
      "Only .jpg, .jpeg, .png and .webp formats are supported."
    )
})

And then the error should be displayed with:

formState.errors?.image?.message

One thing to note though is what kind of object are you getting from your input. Check if its a File object or a File[] array. I am using it with react-dropzone so I configured it to save a single File object. If it were an array you would have to change the schema to this:

const MAX_FILE_SIZE = 5000000;
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png", "image/webp"];

const someSchema = z.object({
  image: z
    .any()
    .refine((files) => files?.[0]?.size <= MAX_FILE_SIZE, `Max image size is 5MB.`)
    .refine(
      (files) => ACCEPTED_IMAGE_TYPES.includes(files?.[0]?.type),
      "Only .jpg, .jpeg, .png and .webp formats are supported."
    )
})
like image 63
zleki Avatar answered Dec 12 '25 08:12

zleki


I encountered the same problem as you did and discovered a simpler way to solve it.

I'm also using Dropzone, but the concept is the same if you're using the File type, as long as it's not a vector file. Just don't use the "transform" and understand that the refinement will be for a single file.

    avatar: z
    .custom<FileList>()
    .transform((file) => file.length > 0 && file.item(0))
    .refine((file) => !file || (!!file && file.size <= 10 * 1024 * 1024), {
      message: "The profile picture must be a maximum of 10MB.",
    })
    .refine((file) => !file || (!!file && file.type?.startsWith("image")), {
      message: "Only images are allowed to be sent.",
    }),
like image 44
Rodrigo Brocchi Avatar answered Dec 12 '25 08:12

Rodrigo Brocchi