我有问题,我需要使用
zod
验证图像。我找了3个小时。我找不到验证图像的信息?谁能帮我解决这个问题吗? zod
必须有图像验证吗?
const payloadSchema = z.object({
image: z.record(z.string()),
})
找到类似的东西,但是如何添加最大 3 mb 的图像,并且其类型必须是“
jpg
”“png
”或“gif
”
试试这个,看起来很简单,而且对我有用:
const MAX_FILE_SIZE = 500000;
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."
)
})
然后错误应该显示为:
formState.errors?.image?.message
需要注意的一件事是您从输入中得到什么样的对象。检查它是否是 File 对象或 File[] 数组。我将它与react-dropzone一起使用,因此我将其配置为保存单个文件对象。如果它是一个数组,您必须将架构更改为:
const MAX_FILE_SIZE = 500000;
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."
)
})
我将通过向
File
的 zod 模式添加改进来解决此问题。 superRefine
帮助器可用于将新问题附加到现有模式作为后续验证。
import { z } from 'zod';
const MB_BYTES = 1000000; // Number of bytes in a megabyte.
// This is the list of mime types you will accept with the schema
const ACCEPTED_MIME_TYPES = ["image/gif", "image/jpeg", "image/png"];
// This is a file validation with a few extra checks in the `superRefine`.
// The `refine` method could also be used, but `superRefine` offers better
// control over when the errors are added and can include specific information
// about the value being parsed.
const imageSchema = z.instanceof(File).superRefine((f, ctx) => {
// First, add an issue if the mime type is wrong.
if (!ACCEPTED_MIME_TYPES.includes(f.type)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `File must be one of [${ACCEPTED_MIME_TYPES.join(
", "
)}] but was ${f.type}`
});
}
// Next add an issue if the file size is too large.
if (f.size > 3 * MB_BYTES) {
ctx.addIssue({
code: z.ZodIssueCode.too_big,
type: "array",
message: `The file must not be larger than ${3 * MB_BYTES} bytes: ${
f.size
}`,
maximum: 3 * MB_BYTES,
inclusive: true
});
}
});
这应该使用您定义的参数进行验证,但假设您拥有正在验证的
File
的句柄。如果您从 <input type="file" />
元素获取文件,则可以通过向输入添加 accept
属性来避免验证 MIME 类型。
我遇到了和你一样的问题,并发现了一个更简单的方法来解决它。
我也在使用 Dropzone,但如果您使用文件类型,概念是相同的,只要它不是矢量文件。只是不要使用“转换”并了解细化将针对单个文件。
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.",
}),
试试这个。这个对我有用。另请检查您是否有文件数组或文件对象并进行相应的更改。如果需要的话,我还添加了文件所需的验证
const MAX_FILE_SIZE = 3000000;
function checkFileType(file: File) { // file type checking
if (file?.name) {
const fileType = file.name.split(".").pop();
if (["gif", "png", "jpg"].includes(fileType)) return true;
}
return false;
}
export const fileSchema = z.object({
z.any()
.refine((file: File) => file?.length !== 0, "File is required") // If you also wanna validate if the file exists
.refine((file) => file.size < MAX_FILE_SIZE, "Max size is 3MB.") // file size validation
.refine((file) => checkFileType(file), "Only .jpg, .gif, .png formats are supported."),`
});