Size limits, count limits, MIME/extension filters, and custom validators
max-file-size)max-file-size accepts bytes or a human suffix (5MB, 300kB, 1.5GB — binary/1024-based units). Files larger than the limit are rejected with code 'size'.
max-file-count)Once the count is reached, subsequent files are rejected with code 'count'.
accept)Files that fail the MIME/extension match are rejected with code 'type'.
Set validateCallback on the element to add custom validation. Return { valid: false, error: '...' } to reject; the failure surfaces alongside built-in validation errors via the files-rejected event.
const el = document.getElementById('custom-validate')
el.validateCallback = (file, existingFiles) => {
if (file.name.includes(' ')) {
return { valid: false, error: 'Filename must not contain spaces' }
}
return { valid: true }
}
beforeFilesAddedCallback and beforeFilesRemovedCallback let you pop a dialog before files actually enter or leave the dropzone. They run AFTER the sync validators pass (size, type, count, validateCallback) and are skipped for programmatic removeFile(id) / clear() calls unless you pass { confirm: true }. Resolving false on the add gate emits files-rejected with code: 'cancelled'.
const el = document.getElementById('confirm-gate')
el.beforeFilesAddedCallback = async (files, existingFiles) => {
const names = files.map(f => f.name).join(', ')
return confirm(`Add ${files.length} file(s)?\n\n${names}`)
}
el.beforeFilesRemovedCallback = async (files, allFiles) => {
if (files.length === 1) {
return confirm(`Remove "${files[0].name}"?`)
}
return confirm(`Remove all ${files.length} files?`)
}
All validation rules apply together. The first failing rule wins.
Each rejection includes a code so you can branch on it programmatically.
el.addEventListener('files-rejected', (e) => {
for (const { file, validation } of e.detail.rejectedFiles) {
switch (validation.code) {
case 'size': showError(`${file.name} is too large`); break
case 'type': showError(`${file.name} type not allowed`); break
case 'count': showError('Too many files'); break
case 'custom': showError(validation.error); break
}
}
})