File Validation
Dropup provides comprehensive file validation to ensure only valid files are accepted.
Validation Options
Accept (File Types)
Specify which file types to accept:
// Accept only images
useDropup({ accept: 'image/*' });
// Accept specific types
useDropup({ accept: 'image/png, image/jpeg' });
// Accept by extension
useDropup({ accept: '.pdf, .doc, .docx' });
// Multiple categories
useDropup({ accept: ['image/*', 'application/pdf', '.txt'] });
Common Accept Patterns
| Pattern | Description |
|---|---|
image/* | All images |
image/png, image/jpeg | Only PNG and JPEG |
video/* | All videos |
audio/* | All audio files |
application/pdf | PDF files only |
.doc, .docx | Word documents |
*/* | All files (default) |
File Size Limits
useDropup({
maxSize: 10 * 1024 * 1024, // 10MB maximum
minSize: 1024, // 1KB minimum
});
File Count Limit
useDropup({
maxFiles: 5, // Maximum 5 files
});
Image Dimension Limits
useDropup({
accept: 'image/*',
maxWidth: 4096, // Max width in pixels
maxHeight: 4096, // Max height in pixels
minWidth: 100, // Min width in pixels
minHeight: 100, // Min height in pixels
});
Custom Validation Rules
Create custom validation logic:
useDropup({
customRules: [
// Rule 1: Check filename length
(file) => {
if (file.name.length > 100) {
return 'Filename must be less than 100 characters';
}
return true;
},
// Rule 2: Check for specific content
(file) => {
if (file.name.includes('draft')) {
return 'Draft files are not allowed';
}
return true;
},
// Rule 3: Async validation
async (file) => {
const hash = await calculateHash(file);
const exists = await checkDuplicate(hash);
if (exists) {
return 'This file has already been uploaded';
}
return true;
},
],
});
Rule Return Values
| Return Value | Meaning |
|---|---|
true | Validation passed |
false | Validation failed (generic error) |
string | Validation failed with custom message |
Handling Validation Errors
Use the onValidationError callback:
useDropup({
accept: 'image/*',
maxSize: 5 * 1024 * 1024,
onValidationError: (errors) => {
errors.forEach(({ file, errors: fileErrors }) => {
console.log(`${file.name} failed validation:`);
fileErrors.forEach(error => console.log(` - ${error}`));
});
// Show user-friendly message
toast.error(`${errors.length} file(s) failed validation`);
},
});
Validation Error Structure
interface ValidationError {
file: File; // The file that failed
errors: string[]; // Array of error messages
}
Pre-built Validation Rules
Dropup includes common validation rules:
import { commonRules } from '@samithahansaka/dropup';
useDropup({
customRules: [
commonRules.noExecutables, // Block .exe, .bat, etc.
commonRules.noHiddenFiles, // Block files starting with .
commonRules.maxFilenameLength(50),
commonRules.allowedExtensions(['.jpg', '.png', '.pdf']),
],
});
Drag Validation Feedback
Provide visual feedback during drag:
function DropZone() {
const { getDropProps, state } = useDropup({
accept: 'image/*',
});
// state.isDragAccept - files match accept criteria
// state.isDragReject - files don't match
return (
<div
{...getDropProps()}
style={{
borderColor: state.isDragAccept
? 'green'
: state.isDragReject
? 'red'
: 'gray',
}}
>
{state.isDragReject && <p>File type not accepted!</p>}
</div>
);
}
Complete Validation Example
import { useDropup, commonRules } from '@samithahansaka/dropup';
function SecureUploader() {
const { files, state, getDropProps, getInputProps } = useDropup({
// File type
accept: ['image/jpeg', 'image/png', 'application/pdf'],
// Size limits
maxSize: 10 * 1024 * 1024, // 10MB
minSize: 100, // 100 bytes (prevent empty files)
// Count limit
maxFiles: 10,
// Image dimensions (for images only)
maxWidth: 8000,
maxHeight: 8000,
// Custom rules
customRules: [
commonRules.noExecutables,
commonRules.maxFilenameLength(100),
// Custom: no files with spaces
(file) => {
if (file.name.includes(' ')) {
return 'Filenames cannot contain spaces';
}
return true;
},
],
// Error handling
onValidationError: (errors) => {
errors.forEach(({ file, errors }) => {
alert(`${file.name}: ${errors.join(', ')}`);
});
},
});
return (
<div
{...getDropProps()}
className={`dropzone ${
state.isDragReject ? 'reject' : state.isDragAccept ? 'accept' : ''
}`}
>
<input {...getInputProps()} />
{state.isDragReject ? (
<p>❌ Some files will be rejected</p>
) : (
<p>📁 Drop files here (JPEG, PNG, PDF only, max 10MB)</p>
)}
</div>
);
}