Xác thực tệp
Dropup cung cấp xác thực tệp toàn diện để đảm bảo chỉ các tệp hợp lệ được chấp nhận.
Tùy chọn xác thực
Accept (Loại tệp)
Chỉ định loại tệp được chấp nhận:
// Chỉ chấp nhận hình ảnh
useDropup({ accept: 'image/*' });
// Chấp nhận các loại cụ thể
useDropup({ accept: 'image/png, image/jpeg' });
// Chấp nhận theo phần mở rộng
useDropup({ accept: '.pdf, .doc, .docx' });
// Nhiều danh mục
useDropup({ accept: ['image/*', 'application/pdf', '.txt'] });
Các mẫu Accept phổ biến
| Mẫu | Mô tả |
|---|---|
image/* | Tất cả hình ảnh |
image/png, image/jpeg | Chỉ PNG và JPEG |
video/* | Tất cả video |
audio/* | Tất cả tệp âm thanh |
application/pdf | Chỉ tệp PDF |
.doc, .docx | Tài liệu Word |
*/* | Tất cả tệp (mặc định) |
Giới hạn kích thước tệp
useDropup({
maxSize: 10 * 1024 * 1024, // Tối đa 10MB
minSize: 1024, // Tối thiểu 1KB
});
Giới hạn số lượng tệp
useDropup({
maxFiles: 5, // Tối đa 5 tệp
});
Giới hạn kích thước hình ảnh
useDropup({
accept: 'image/*',
maxWidth: 4096, // Chiều rộng tối đa tính bằng pixel
maxHeight: 4096, // Chiều cao tối đa tính bằng pixel
minWidth: 100, // Chiều rộng tối thiểu tính bằng pixel
minHeight: 100, // Chiều cao tối thiểu tính bằng pixel
});
Quy tắc xác thực tùy chỉnh
Tạo logic xác thực tùy chỉnh:
useDropup({
customRules: [
// Quy tắc 1: Kiểm tra độ dài tên tệp
(file) => {
if (file.name.length > 100) {
return 'Tên tệp phải ít hơn 100 ký tự';
}
return true;
},
// Quy tắc 2: Kiểm tra nội dung cụ thể
(file) => {
if (file.name.includes('draft')) {
return 'Không cho phép tệp nháp';
}
return true;
},
// Quy tắc 3: Xác thực bất đồng bộ
async (file) => {
const hash = await calculateHash(file);
const exists = await checkDuplicate(hash);
if (exists) {
return 'Tệp này đã được tải lên';
}
return true;
},
],
});
Giá trị trả về của quy tắc
| Giá trị trả về | Ý nghĩa |
|---|---|
true | Xác thực thành công |
false | Xác thực thất bại (lỗi chung) |
string | Xác thực thất bại với thông báo tùy chỉnh |
Xử lý lỗi xác thực
Sử dụng callback onValidationError:
useDropup({
accept: 'image/*',
maxSize: 5 * 1024 * 1024,
onValidationError: (errors) => {
errors.forEach(({ file, errors: fileErrors }) => {
console.log(`${file.name} xác thực thất bại:`);
fileErrors.forEach(error => console.log(` - ${error}`));
});
// Hiển thị thông báo thân thiện với người dùng
toast.error(`${errors.length} tệp xác thực thất bại`);
},
});
Cấu trúc lỗi xác thực
interface ValidationError {
file: File; // Tệp thất bại
errors: string[]; // Mảng thông báo lỗi
}
Quy tắc xác thực có sẵn
Dropup bao gồm các quy tắc xác thực phổ biến:
import { commonRules } from '@samithahansaka/dropup';
useDropup({
customRules: [
commonRules.noExecutables, // Chặn .exe, .bat, v.v.
commonRules.noHiddenFiles, // Chặn tệp bắt đầu bằng .
commonRules.maxFilenameLength(50),
commonRules.allowedExtensions(['.jpg', '.png', '.pdf']),
],
});
Phản hồi xác thực khi kéo
Cung cấp phản hồi trực quan khi kéo:
function DropZone() {
const { getDropProps, state } = useDropup({
accept: 'image/*',
});
// state.isDragAccept - tệp khớp với tiêu chí accept
// state.isDragReject - tệp không khớp
return (
<div
{...getDropProps()}
style={{
borderColor: state.isDragAccept
? 'green'
: state.isDragReject
? 'red'
: 'gray',
}}
>
{state.isDragReject && <p>Loại tệp không được chấp nhận!</p>}
</div>
);
}
Ví dụ xác thực hoàn chỉnh
import { useDropup, commonRules } from '@samithahansaka/dropup';
function SecureUploader() {
const { files, state, getDropProps, getInputProps } = useDropup({
// Loại tệp
accept: ['image/jpeg', 'image/png', 'application/pdf'],
// Giới hạn kích thước
maxSize: 10 * 1024 * 1024, // 10MB
minSize: 100, // 100 bytes (ngăn tệp rỗng)
// Giới hạn số lượng
maxFiles: 10,
// Kích thước hình ảnh (chỉ cho hình ảnh)
maxWidth: 8000,
maxHeight: 8000,
// Quy tắc tùy chỉnh
customRules: [
commonRules.noExecutables,
commonRules.maxFilenameLength(100),
// Tùy chỉnh: không có tệp có khoảng trắng
(file) => {
if (file.name.includes(' ')) {
return 'Tên tệp không được chứa khoảng trắng';
}
return true;
},
],
// Xử lý lỗi
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>Một số tệp sẽ bị từ chối</p>
) : (
<p>Thả tệp vào đây (chỉ JPEG, PNG, PDF, tối đa 10MB)</p>
)}
</div>
);
}