Validating file size and format with YUP
Asked Answered
P

7

22

I have a form using reactjs + formik + yup. I have a multi file upload field. I want to validate the file format and max size using yup. How can I do this?

Pryor answered 3/1, 2019 at 10:43 Comment(0)
D
22

Expanding on Devin's answer, you can implement that validation with yup.

    const schema = Yup.object().shape({
       files: Yup.array()
         .nullable()
         .required('VALIDATION_FIELD_REQUIRED')
         .test('is-correct-file', 'VALIDATION_FIELD_FILE_BIG', checkIfFilesAreTooBig)
         .test(
           'is-big-file',
           'VALIDATION_FIELD_FILE_WRONG_TYPE',
           checkIfFilesAreCorrectType
         ),
})

Where the validation functions are:

export function checkIfFilesAreTooBig(files?: [File]): boolean {
  let valid = true
  if (files) {
    files.map(file => {
      const size = file.size / 1024 / 1024
      if (size > 10) {
        valid = false
      }
    })
  }
  return valid
}

export function checkIfFilesAreCorrectType(files?: [File]): boolean {
  let valid = true
  if (files) {
    files.map(file => {
      if (!['application/pdf', 'image/jpeg', 'image/png'].includes(file.type)) {
        valid = false
      }
    })
  }
  return valid
}
Delayedaction answered 8/4, 2019 at 9:56 Comment(0)
E
7
export const UploadFileSchema = yup.object().shape({
file: yup
    .mixed()
    .required("You need to provide a file")
    .test("fileSize", "The file is too large", (value) => {
        return value && value[0].sienter code hereze <= 2000000;
    })
    .test("type", "Only the following formats are accepted: .jpeg, .jpg, .bmp, .pdf and .doc", (value) => {
        return value && (
            value[0].type === "image/jpeg" ||
            value[0].type === "image/bmp" ||
            value[0].type === "image/png" ||
            value[0].type === 'application/pdf' ||
            value[0].type === "application/msword"
        );
    }),
});

This solution is taken from Maksim Ivanov (on youtube)

Earsplitting answered 26/1, 2021 at 11:58 Comment(1)
I'm not sure about Formik but this didn't work with React Hook Form. The problem with RHF is that the file field will never be empty. Without files, it will contain an empty FileList. To check the required requirement you'd need to white your own validator function. Here is a link to the file with this kind of validation implemented.Buddleia
Q
5
  const SUPPORTED_FORMATS = ['image/jpg', 'image/jpeg', 'image/png'];

  const registerSchema = Yup.object().shape({
    uriImage: Yup.mixed()
      .nullable()
      .required('A file is required')
      .test('Fichier taille',
        'upload file', (value) => !value || (value && value.size <= 1024 * 1024))
      .test('format',
        'upload file', (value) => !value || (value && SUPPORTED_FORMATS.includes(value.type))),
  });
Quahog answered 24/11, 2021 at 15:2 Comment(0)
D
4

image:

Yup.mixed().test(1000, "File Size is too large", value => value.size <= FILE_SIZE) .test('fileType', "Unsupported File Format", value => SUPPORTED_FORMATS.includes(['image/*']) )

https://hackernoon.com/formik-handling-files-and-recaptcha-209cbeae10bc

Deep answered 14/4, 2022 at 11:40 Comment(0)
B
3

This code will work for validating image formats.

const SUPPORTED_FORMATS = ["image/jpg", "image/jpeg", "image/gif", "image/png"];

export const validateImageType = (value) => {
  if(value) {
    let type = value.match(/[^:]\w+\/[\w-+\d.]+(?=;|,)/)[0]
    return SUPPORTED_FORMATS.includes(type)
  }
}

  Yup.mixed() .test('fileSize', "File is too large", value => value.size <= FILE_SIZE) .test('fileType', "Your Error Message", value => SUPPORTED_FORMATS.includes(value.type) )
Brawn answered 20/1, 2020 at 8:49 Comment(3)
You can add this for size validation Yup.mixed().test('fileSize', "File Size is too large", value => value.size <= FILE_SIZE)Brawn
Where do you use this function "validateImageType"?Comyns
It should be the third parameter of the test functionBrawn
G
0

Based on pfulop's answer, here's how I had to do it, to make it work:

const maxFileSize = 800 * 1024 // 800 kilobytes
const fileTypes = ['image/png', 'image/jpg', 'image/jpeg']

const schema = yup.object().shape({
  first_name: yup.string().required(),
  last_name: yup.string().required(),
  email: yup.string().email().required(),
  avatar: yup.mixed().test('fileSize', appTranslation.ERROR_FILE_SIZE, (value) => {
    if (!value) return true
    return isFileSizeValid([value], maxFileSize)
  }).test('fileType', appTranslation.ERROR_FILE_TYPE, (value) => {
    if (!value) return true
    return isFileTypesValid([value], fileTypes)
  })
})

export function isFileSizeValid(files: [File], maxSize: number): boolean {
    let valid = true
    if (files) {
        files.map(file => {
            const fileSize = file.size
            if (fileSize > maxSize) {
                valid = false
            }
        })
    }
    return valid
}

export function isFileTypesValid(files: [File], authorizedExtensions: string[]): boolean {
    let valid = true
    if (files) {
        files.map(file => {
            if (!authorizedExtensions.includes(file.type)) {
                valid = false
            }
        })
    }
    return valid
}

I reuse functions in my code, which is why I've added maxSize & authorizedExtensions or the export keyword. The most important change is to const schema.

Gause answered 28/6, 2023 at 9:1 Comment(0)
K
0

My Yup validation file for size and extensions

import * as Yup from 'yup';

const validFileExtensions = { extensions: ['jpg', 'png', 'pdf'] };

function isValidFileType(fileName, fileType) {
    return fileName && validFileExtensions[fileType].indexOf(fileName.split('.').pop()) > -1;
}

export const validationYourNameSchema = Yup.object().shape({
      file: Yup.mixed()
        .required('A file is requeued')
        .test('fileSize', 'File exceeds the maximum supported size of 14 MB', (value) => {
            return value && value.size <= 1024 * 1024 * 14
        }) 
        .test('is-valid-type', 
            'Invalid file extension. Allow downloading only files in PNG, JPG, PDF formats.', (value) => {
                return isValidFileType(value && value.name.toLowerCase(), 'extensions')
            }) 
})


Kennithkennon answered 2/4 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.