ComCool
ComCool

Reputation: 1103

Validating file size and format with YUP

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?

Upvotes: 22

Views: 53995

Answers (7)

Ivan K.
Ivan K.

Reputation: 1094

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')
            }) 
})


Upvotes: 0

Elell
Elell

Reputation: 15

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.

Upvotes: 0

AdekunleCodez
AdekunleCodez

Reputation: 164

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

Upvotes: 4

jacobit kashala
jacobit kashala

Reputation: 79

  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))),
  });

Upvotes: 5

roniccolo
roniccolo

Reputation: 158

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)

Upvotes: 7

Musab Akram
Musab Akram

Reputation: 163

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) )

Upvotes: 3

pfulop
pfulop

Reputation: 1009

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
}

Upvotes: 22

Related Questions