Валидация файлов
Dropup предоставляет комплексную валидацию файлов, чтобы гарантировать принятие только валидных файлов.
Опции валидации
Accept (Типы файлов)
Укажите, какие типы файлов принимать:
// Принимать только изображения
useDropup({ accept: 'image/*' });
// Принимать определённые типы
useDropup({ accept: 'image/png, image/jpeg' });
// Принимать по расширению
useDropup({ accept: '.pdf, .doc, .docx' });
// Несколько категорий
useDropup({ accept: ['image/*', 'application/pdf', '.txt'] });
Общие паттерны Accept
| Паттерн | Описание |
|---|---|
image/* | Все изображения |
image/png, image/jpeg | Только PNG и JPEG |
video/* | Все видео |
audio/* | Все аудиофайлы |
application/pdf | Только PDF файлы |
.doc, .docx | Документы Word |
*/* | Все файлы (по умолчанию) |
Ограничения размера файла
useDropup({
maxSize: 10 * 1024 * 1024, // Максимум 10МБ
minSize: 1024, // Минимум 1КБ
});
Ограничение количества файлов
useDropup({
maxFiles: 5, // Максимум 5 файлов
});
Ограничения размеров изображений
useDropup({
accept: 'image/*',
maxWidth: 4096, // Максимальная ширина в пикселях
maxHeight: 4096, // Максимальная высота в пикселях
minWidth: 100, // Минимальная ширина в пикселях
minHeight: 100, // Минимальная высота в пикселях
});
Пользовательские правила валидации
Создайте собственную логику валидации:
useDropup({
customRules: [
// Правило 1: Проверка длины имени файла
(file) => {
if (file.name.length > 100) {
return 'Имя файла должно быть короче 100 символов';
}
return true;
},
// Правило 2: Проверка на определённое содержимое
(file) => {
if (file.name.includes('draft')) {
return 'Черновики не допускаются';
}
return true;
},
// Правило 3: Асинхронная валидация
async (file) => {
const hash = await calculateHash(file);
const exists = await checkDuplicate(hash);
if (exists) {
return 'Этот файл уже был загружен';
}
return true;
},
],
});
Возвращаемые значения правил
| Возвращаемое значение | Значение |
|---|---|
true | Валидация пройдена |
false | Валидация не пройдена (общая ошибка) |
string | Валидация не пройдена с пользовательским сообщением |
Обработка ошибок валидации
Используйте колбэк onValidationError:
useDropup({
accept: 'image/*',
maxSize: 5 * 1024 * 1024,
onValidationError: (errors) => {
errors.forEach(({ file, errors: fileErrors }) => {
console.log(`${file.name} не прошёл валидацию:`);
fileErrors.forEach(error => console.log(` - ${error}`));
});
// Показать понятное сообщение пользователю
toast.error(`${errors.length} файл(ов) не прошли валидацию`);
},
});
Структура ошибки валидации
interface ValidationError {
file: File; // Файл, который не прошёл проверку
errors: string[]; // Массив сообщений об ошибках
}
Встроенные правила валидации
Dropup включает общие правила валидации:
import { commonRules } from '@samithahansaka/dropup';
useDropup({
customRules: [
commonRules.noExecutables, // Блокировать .exe, .bat и т.д.
commonRules.noHiddenFiles, // Блокировать файлы, начинающиеся с .
commonRules.maxFilenameLength(50),
commonRules.allowedExtensions(['.jpg', '.png', '.pdf']),
],
});
Обратная связь при перетаскивании
Предоставьте визуальную обратную связь при перетаскивании:
function DropZone() {
const { getDropProps, state } = useDropup({
accept: 'image/*',
});
// state.isDragAccept - файлы соответствуют критериям accept
// state.isDragReject - файлы не соответствуют
return (
<div
{...getDropProps()}
style={{
borderColor: state.isDragAccept
? 'green'
: state.isDragReject
? 'red'
: 'gray',
}}
>
{state.isDragReject && <p>Тип файла не поддерживается!</p>}
</div>
);
}
Полный пример валидации
import { useDropup, commonRules } from '@samithahansaka/dropup';
function SecureUploader() {
const { files, state, getDropProps, getInputProps } = useDropup({
// Тип файла
accept: ['image/jpeg', 'image/png', 'application/pdf'],
// Ограничения размера
maxSize: 10 * 1024 * 1024, // 10МБ
minSize: 100, // 100 байт (предотвратить пустые файлы)
// Ограничение количества
maxFiles: 10,
// Размеры изображений (только для изображений)
maxWidth: 8000,
maxHeight: 8000,
// Пользовательские правила
customRules: [
commonRules.noExecutables,
commonRules.maxFilenameLength(100),
// Пользовательское: без пробелов в имени
(file) => {
if (file.name.includes(' ')) {
return 'Имя файла не может содержать пробелы';
}
return true;
},
],
// Обработка ошибок
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>❌ Некоторые файлы будут отклонены</p>
) : (
<p>📁 Перетащите файлы сюда (только JPEG, PNG, PDF, макс. 10МБ)</p>
)}
</div>
);
}