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?
Asked
Active
Viewed 4.3k times
6 Answers
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
}

pfulop
- 1,009
- 13
- 24
6
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)
-
1I'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](https://github.com/satansdeer/rhf-validate-file/blob/95e96d26e2645cb04554aa5f1ef679e70f42ecbf/src/App.js#L7-L18) to the file with this kind of validation implemented. – SatansDeer Nov 03 '21 at 15:03
4
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))),
});

jacobit kashala
- 41
- 2
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) )

Musab Akram
- 163
- 10
-
You can add this for size validation Yup.mixed().test('fileSize', "File Size is too large", value => value.size <= FILE_SIZE) – Musab Akram Jan 20 '20 at 08:50
-
1
-
3
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

Jakub Kurdziel
- 3,216
- 2
- 12
- 22

AdekunleCodez
- 120
- 1
- 1
- 8
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.

Elell
- 15
- 2