Lewati ke konten utama

Validasi File

Dropup menyediakan validasi file yang komprehensif untuk memastikan hanya file yang valid yang diterima.

Opsi Validasi

Accept (Tipe File)

Tentukan tipe file mana yang diterima:

// Hanya terima gambar
useDropup({ accept: 'image/*' });

// Terima tipe tertentu
useDropup({ accept: 'image/png, image/jpeg' });

// Terima berdasarkan ekstensi
useDropup({ accept: '.pdf, .doc, .docx' });

// Multiple kategori
useDropup({ accept: ['image/*', 'application/pdf', '.txt'] });

Pola Accept Umum

PolaDeskripsi
image/*Semua gambar
image/png, image/jpegHanya PNG dan JPEG
video/*Semua video
audio/*Semua file audio
application/pdfHanya file PDF
.doc, .docxDokumen Word
*/*Semua file (default)

Batas Ukuran File

useDropup({
maxSize: 10 * 1024 * 1024, // 10MB maksimum
minSize: 1024, // 1KB minimum
});

Batas Jumlah File

useDropup({
maxFiles: 5, // Maksimum 5 file
});

Batas Dimensi Gambar

useDropup({
accept: 'image/*',
maxWidth: 4096, // Lebar maks dalam pixel
maxHeight: 4096, // Tinggi maks dalam pixel
minWidth: 100, // Lebar min dalam pixel
minHeight: 100, // Tinggi min dalam pixel
});

Aturan Validasi Kustom

Buat logika validasi kustom:

useDropup({
customRules: [
// Aturan 1: Periksa panjang nama file
(file) => {
if (file.name.length > 100) {
return 'Nama file harus kurang dari 100 karakter';
}
return true;
},

// Aturan 2: Periksa konten tertentu
(file) => {
if (file.name.includes('draft')) {
return 'File draft tidak diperbolehkan';
}
return true;
},

// Aturan 3: Validasi async
async (file) => {
const hash = await calculateHash(file);
const exists = await checkDuplicate(hash);
if (exists) {
return 'File ini sudah pernah diupload';
}
return true;
},
],
});

Nilai Return Aturan

Nilai ReturnMakna
trueValidasi berhasil
falseValidasi gagal (error generik)
stringValidasi gagal dengan pesan kustom

Menangani Error Validasi

Gunakan callback onValidationError:

useDropup({
accept: 'image/*',
maxSize: 5 * 1024 * 1024,
onValidationError: (errors) => {
errors.forEach(({ file, errors: fileErrors }) => {
console.log(`${file.name} gagal validasi:`);
fileErrors.forEach(error => console.log(` - ${error}`));
});

// Tampilkan pesan yang ramah pengguna
toast.error(`${errors.length} file gagal validasi`);
},
});

Struktur Error Validasi

interface ValidationError {
file: File; // File yang gagal
errors: string[]; // Array pesan error
}

Aturan Validasi Bawaan

Dropup menyertakan aturan validasi umum:

import { commonRules } from '@samithahansaka/dropup';

useDropup({
customRules: [
commonRules.noExecutables, // Blokir .exe, .bat, dll.
commonRules.noHiddenFiles, // Blokir file yang dimulai dengan .
commonRules.maxFilenameLength(50),
commonRules.allowedExtensions(['.jpg', '.png', '.pdf']),
],
});

Feedback Validasi Seret

Berikan feedback visual saat menyeret:

function DropZone() {
const { getDropProps, state } = useDropup({
accept: 'image/*',
});

// state.isDragAccept - file cocok dengan kriteria accept
// state.isDragReject - file tidak cocok

return (
<div
{...getDropProps()}
style={{
borderColor: state.isDragAccept
? 'green'
: state.isDragReject
? 'red'
: 'gray',
}}
>
{state.isDragReject && <p>Tipe file tidak diterima!</p>}
</div>
);
}

Contoh Validasi Lengkap

import { useDropup, commonRules } from '@samithahansaka/dropup';

function SecureUploader() {
const { files, state, getDropProps, getInputProps } = useDropup({
// Tipe file
accept: ['image/jpeg', 'image/png', 'application/pdf'],

// Batas ukuran
maxSize: 10 * 1024 * 1024, // 10MB
minSize: 100, // 100 bytes (cegah file kosong)

// Batas jumlah
maxFiles: 10,

// Dimensi gambar (hanya untuk gambar)
maxWidth: 8000,
maxHeight: 8000,

// Aturan kustom
customRules: [
commonRules.noExecutables,
commonRules.maxFilenameLength(100),

// Kustom: tidak ada file dengan spasi
(file) => {
if (file.name.includes(' ')) {
return 'Nama file tidak boleh mengandung spasi';
}
return true;
},
],

// Penanganan error
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>❌ Beberapa file akan ditolak</p>
) : (
<p>📁 Lepas file di sini (hanya JPEG, PNG, PDF, maks 10MB)</p>
)}
</div>
);
}