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?
Validating file size and format with YUP
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
}
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)
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))),
});
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
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) )
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 function –
Brawn
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.
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')
})
})
© 2022 - 2024 — McMap. All rights reserved.
FileList
. To check therequired
requirement you'd need to white your own validator function. Here is a link to the file with this kind of validation implemented. – Buddleia