使用 Yup 和 formik 验证图像的纵横比(宽度/高度)

我正在尝试使用 yup 对图像文件进行验证,我发现https://github.com/formium/formik/issues/926只验证大小和文件类型。

这是我当前使用的 yup 验证

file: lazy(value => {

    switch (typeof value) {

      case 'string':

        return string().required(errorHandler.requiredFile());

      default:

        return mixed()

          .required(errorHandler.requiredFile())

          .test(

            'fileSize',

            'Size',

            value => value && value.size <= FILE_SIZE

          )

          .test(

            'fileType',

            'Format',

            value => value && SUPPORTED_FORMATS.includes(value.type)

          )

    }

  }),

我该怎么做?



POPMUISE
浏览 126回答 4
4回答

米脂

创建一个将加载图像文件并返回尺寸的承诺const imageWidthAndHeight = (provideFile) => {&nbsp; &nbsp; // take the given file (which should be an image) and return the width and height&nbsp; &nbsp; const imgDimensions = { width: null, height: null };&nbsp; &nbsp; return new Promise(resolve => {&nbsp; &nbsp; &nbsp; &nbsp; const reader = new FileReader();&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; reader.readAsDataURL(provideFile);&nbsp; &nbsp; &nbsp; &nbsp; reader.onload = function () {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const img = new Image();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img.src = reader.result;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img.onload = function () {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgDimensions.width = img.width;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgDimensions.height = img.height;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(imgDimensions);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; });}在自定义 yup 函数中调用并等待 Promise(使用 addMethod),并添加额外的验证来检查宽度和高度。const imageDimensionCheck = Yup.addMethod(Yup.mixed, 'imageDimensionCheck', function (message, requiredWidth, requiredHeight) {&nbsp; &nbsp; return this.test("image-width-height-check", message, async function (value) {&nbsp; &nbsp; &nbsp; &nbsp; const { path, createError } = this;&nbsp; &nbsp; &nbsp; &nbsp; if (!value) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; const imgDimensions = await imageWidthAndHeight(value);&nbsp; &nbsp; &nbsp; &nbsp; if (imgDimensions.width !== requiredWidth) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return createError({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; path,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message: `The file width needs to be the ${requiredWidth}px!`&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (imgDimensions.height !== requiredHeight) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return createError({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; path,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message: `The file height needs to be the ${requiredHeight}px!`&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; });});在formik中调用创建的Yup方法<Formik&nbsp; &nbsp; initialValues={{&nbsp; &nbsp; &nbsp; &nbsp; bookCoverPhoto: null,&nbsp; &nbsp; }}&nbsp; &nbsp; validationSchema={&nbsp; &nbsp; &nbsp; &nbsp; Yup.object().shape({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bookCoverPhoto: Yup.mixed()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .required('You need to provide a file')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .imageDimensionCheck('test', 1988, 3056)&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; }>....Stuff</Formik>

冉冉说

这里有两种替代方法,它们比 Base64 编码(解码)更快,并且不需要文件读取器function checkAspectRatio (file) {&nbsp; &nbsp; const img = new Image()&nbsp; &nbsp; img.src = URL.createObjectURL(file)&nbsp; &nbsp; return img.decode().then(() => {&nbsp; &nbsp; &nbsp; &nbsp; URL.revokeObjectURL(img.src)&nbsp; &nbsp; &nbsp; &nbsp; return img.width / img.height&nbsp; &nbsp; })}// not as cross compatiblefunction checkAspectRatio (file) {&nbsp; &nbsp; return createImageBitmap(file)&nbsp; &nbsp; &nbsp; .then(bitmap => bitmap.width / bitmap.height)}

梦里花落0921

image: Yup.mixed()&nbsp; .required("Image is required.")&nbsp; .test(&nbsp; &nbsp; "aspectRatio",&nbsp; &nbsp; "Aspect ratio must be 16:9",&nbsp; &nbsp; value => {&nbsp; &nbsp; &nbsp; return new Promise(resolve => {&nbsp; &nbsp; &nbsp; &nbsp; const reader = new FileReader();&nbsp; &nbsp; &nbsp; &nbsp; reader.readAsDataURL(value[0]);&nbsp; &nbsp; &nbsp; &nbsp; reader.onload = function(value) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const img = new Image();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img.src = value.target.result;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img.onload = function() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const aspectRatio = this.width / this.height;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(aspectRatio === (16 / 9));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; ),

慕勒3428872

我设法使用这个功能来做到这一点function checkAspectRatio(value) {&nbsp; return new Promise(resolve => {&nbsp; &nbsp; const reader = new FileReader();&nbsp; &nbsp; reader.readAsDataURL(value);&nbsp; &nbsp; reader.onload = function(value) {&nbsp; &nbsp; &nbsp; const img = new Image();&nbsp; &nbsp; &nbsp; img.src = value.target.result;&nbsp; &nbsp; &nbsp; img.onload = function() {&nbsp; &nbsp; &nbsp; &nbsp; const aspectRatio = this.width / this.height;&nbsp; &nbsp; &nbsp; &nbsp; resolve(aspectRatio);&nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; };&nbsp; });}用于Object.defineProperty()在对象上定义新属性Object.defineProperty(file, 'aspectRatio', {&nbsp; value: await checkAspectRatio(file)});并使用 yup 测试该值.test(&nbsp; 'fileAspectRatio',&nbsp; 'Please recheck the image resolution',&nbsp; value => value && value.aspectRatio === 1.6);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript