为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

POPMUISE 2023-09-07 16:53:21
我正在尝试使用 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)          )    }  }),我该怎么做?
查看完整描述

4 回答

?
米脂

TA贡献1836条经验 获得超3个赞

创建一个将加载图像文件并返回尺寸的承诺

const imageWidthAndHeight = (provideFile) => {

    // take the given file (which should be an image) and return the width and height

    const imgDimensions = { width: null, height: null };


    return new Promise(resolve => {

        const reader = new FileReader();

        

        reader.readAsDataURL(provideFile);

        reader.onload = function () {

            const img = new Image();

            img.src = reader.result;


            img.onload = function () {

                imgDimensions.width = img.width;

                imgDimensions.height = img.height;


                resolve(imgDimensions);

            }

        };

    });

}

在自定义 yup 函数中调用并等待 Promise(使用 addMethod),并添加额外的验证来检查宽度和高度。

const imageDimensionCheck = Yup.addMethod(Yup.mixed, 'imageDimensionCheck', function (message, requiredWidth, requiredHeight) {

    return this.test("image-width-height-check", message, async function (value) {

        const { path, createError } = this;


        if (!value) {

            return;

        }


        const imgDimensions = await imageWidthAndHeight(value);


        if (imgDimensions.width !== requiredWidth) {

            return createError({

                path,

                message: `The file width needs to be the ${requiredWidth}px!`

              });

        }


        if (imgDimensions.height !== requiredHeight) {

            return createError({

                path,

                message: `The file height needs to be the ${requiredHeight}px!`

              });

        }


        return true;

    });

});

在formik中调用创建的Yup方法

<Formik

    initialValues={{

        bookCoverPhoto: null,

    }}


    validationSchema={

        Yup.object().shape({

            bookCoverPhoto: Yup.mixed()

                .required('You need to provide a file')

                .imageDimensionCheck('test', 1988, 3056)

        })

    }

>

....Stuff

</Formik>


查看完整回答
反对 回复 2023-09-07
?
冉冉说

TA贡献1877条经验 获得超1个赞

这里有两种替代方法,它们比 Base64 编码(解码)更快,并且不需要文件读取器


function checkAspectRatio (file) {

    const img = new Image()

    img.src = URL.createObjectURL(file)

    return img.decode().then(() => {

        URL.revokeObjectURL(img.src)

        return img.width / img.height

    })

}


// not as cross compatible

function checkAspectRatio (file) {

    return createImageBitmap(file)

      .then(bitmap => bitmap.width / bitmap.height)

}


查看完整回答
反对 回复 2023-09-07
?
梦里花落0921

TA贡献1772条经验 获得超6个赞

image: Yup.mixed()

  .required("Image is required.")

  .test(

    "aspectRatio",

    "Aspect ratio must be 16:9",

    value => {

      return new Promise(resolve => {

        const reader = new FileReader();

        reader.readAsDataURL(value[0]);

        reader.onload = function(value) {

          const img = new Image();

          img.src = value.target.result;

          img.onload = function() {

            const aspectRatio = this.width / this.height;

            resolve(aspectRatio === (16 / 9));

          };

        };

      });

    }

  ),


查看完整回答
反对 回复 2023-09-07
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

我设法使用这个功能来做到这一点


function checkAspectRatio(value) {

  return new Promise(resolve => {

    const reader = new FileReader();

    reader.readAsDataURL(value);

    reader.onload = function(value) {

      const img = new Image();

      img.src = value.target.result;

      img.onload = function() {

        const aspectRatio = this.width / this.height;

        resolve(aspectRatio);

      };

    };

  });

}


用于Object.defineProperty()在对象上定义新属性


Object.defineProperty(file, 'aspectRatio', {

  value: await checkAspectRatio(file)

});


并使用 yup 测试该值


.test(

  'fileAspectRatio',

  'Please recheck the image resolution',

  value => value && value.aspectRatio === 1.6

);


查看完整回答
反对 回复 2023-09-07
  • 4 回答
  • 0 关注
  • 125 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信