ຂ້າມໄປຫາເນື້ອຫາຫຼັກ

ການກວດສອບແບບກຳນົດເອງ

ສ້າງກົດລະບຽບການກວດສອບທີ່ຊັບຊ້ອນສຳລັບການອັບໂຫຼດຂອງທ່ານ.

ກົດລະບຽບແບບກຳນົດເອງພື້ນຖານ

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

function CustomValidationUploader() {
const { files, getDropProps, getInputProps } = useDropup({
customRules: [
// ກົດ 1: ກວດສອບຊື່ໄຟລ໌
(file) => {
if (file.name.includes(' ')) {
return 'ຊື່ໄຟລ໌ບໍ່ສາມາດມີຊ່ອງຫວ່າງໄດ້';
}
return true;
},

// ກົດ 2: ກວດສອບນາມສະກຸນ
(file) => {
const ext = file.name.split('.').pop()?.toLowerCase();
const blocked = ['exe', 'bat', 'cmd', 'sh'];
if (ext && blocked.includes(ext)) {
return 'ໄຟລ໌ທີ່ສາມາດ execute ໄດ້ບໍ່ອະນຸຍາດ';
}
return true;
},
],

onValidationError: (errors) => {
errors.forEach(({ file, errors }) => {
alert(`${file.name}:\n${errors.join('\n')}`);
});
},
});

return (
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>ວາງໄຟລ໌ທີ່ນີ້ (ບໍ່ມີຊ່ອງຫວ່າງໃນຊື່, ບໍ່ມີໄຟລ໌ executable)</p>
</div>
);
}

ການກວດສອບແບບ Async

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

function AsyncValidationUploader() {
const { files, getDropProps, getInputProps } = useDropup({
customRules: [
// ກວດສອບການຊ້ຳກັນຢູ່ເຊີບເວີ
async (file) => {
const hash = await calculateHash(file);
const response = await fetch('/api/check-duplicate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ hash, filename: file.name }),
});
const { exists } = await response.json();

if (exists) {
return 'ໄຟລ໌ນີ້ຖືກອັບໂຫຼດແລ້ວ';
}
return true;
},

// ກວດສອບເນື້ອຫາໄຟລ໌
async (file) => {
if (file.type === 'application/json') {
const text = await file.text();
try {
JSON.parse(text);
return true;
} catch {
return 'ໄຟລ໌ JSON ບໍ່ຖືກຕ້ອງ';
}
}
return true;
},
],
});

return (
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>ວາງໄຟລ໌ທີ່ນີ້ (ຖືກກວດສອບກັບເຊີບເວີ)</p>
</div>
);
}

// ຟັງຊັນຊ່ວຍໃນການຄຳນວນ hash ໄຟລ໌
async function calculateHash(file: File): Promise<string> {
const buffer = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

ການກວດສອບເນື້ອຫາຮູບພາບ

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

function ImageContentValidator() {
const { files, getDropProps, getInputProps } = useDropup({
accept: 'image/*',

customRules: [
// ກວດສອບຂະໜາດຮູບພາບຕົວຈິງ
async (file) => {
if (!file.type.startsWith('image/')) return true;

const dimensions = await getImageDimensions(file);

if (dimensions.width < 200 || dimensions.height < 200) {
return 'ຮູບພາບຕ້ອງມີຢ່າງໜ້ອຍ 200x200 pixels';
}

if (dimensions.width > 4000 || dimensions.height > 4000) {
return 'ຮູບພາບບໍ່ສາມາດເກີນ 4000x4000 pixels';
}

return true;
},

// ກວດສອບອັດຕາສ່ວນ
async (file) => {
if (!file.type.startsWith('image/')) return true;

const { width, height } = await getImageDimensions(file);
const ratio = width / height;

// ຕ້ອງການຮູບພາບທີ່ເປັນສີ່ຫຼ່ຽມ (ອັດຕາສ່ວນ 0.8 ຫາ 1.2)
if (ratio < 0.8 || ratio > 1.2) {
return 'ຮູບພາບຕ້ອງເປັນສີ່ຫຼ່ຽມໂດຍປະມານ (ອັດຕາສ່ວນ 0.8-1.2)';
}

return true;
},
],
});

return (
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>ວາງຮູບພາບສີ່ຫຼ່ຽມ (ຕ່ຳສຸດ 200px, ສູງສຸດ 4000px)</p>

<div style={styles.gallery}>
{files.map(file => (
<img
key={file.id}
src={file.preview}
alt=""
style={styles.preview}
/>
))}
</div>
</div>
);
}

// ຟັງຊັນຊ່ວຍເພື່ອດຶງຂະໜາດຮູບພາບ
function getImageDimensions(file: File): Promise<{ width: number; height: number }> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve({ width: img.width, height: img.height });
URL.revokeObjectURL(img.src);
};
img.onerror = reject;
img.src = URL.createObjectURL(file);
});
}

const styles = {
dropzone: {
border: '2px dashed #ccc',
borderRadius: 8,
padding: 40,
textAlign: 'center' as const,
},
gallery: {
display: 'flex',
gap: 8,
marginTop: 16,
justifyContent: 'center',
},
preview: {
width: 80,
height: 80,
objectFit: 'cover' as const,
borderRadius: 4,
},
};

ການກວດສອບກັບ Dependencies

import { useDropup } from '@samithahansaka/dropup';
import { useState } from 'react';

function ConditionalValidation() {
const [category, setCategory] = useState('image');

const { files, getDropProps, getInputProps } = useDropup({
// accept ແບບ dynamic ຕາມປະເພດ
accept: category === 'image'
? 'image/*'
: category === 'document'
? '.pdf,.doc,.docx'
: '*/*',

customRules: [
(file) => {
// ການກວດສອບສະເພາະປະເພດ
if (category === 'image') {
if (!file.type.startsWith('image/')) {
return 'ກະລຸນາອັບໂຫຼດໄຟລ໌ຮູບພາບ';
}
if (file.size > 5 * 1024 * 1024) {
return 'ຮູບພາບຕ້ອງນ້ອຍກວ່າ 5MB';
}
}

if (category === 'document') {
if (file.size > 10 * 1024 * 1024) {
return 'ເອກະສານຕ້ອງນ້ອຍກວ່າ 10MB';
}
}

return true;
},
],
});

return (
<div>
<div style={{ marginBottom: 20 }}>
<label>
<input
type="radio"
value="image"
checked={category === 'image'}
onChange={() => setCategory('image')}
/>
ຮູບພາບ (ສູງສຸດ 5MB)
</label>
<label style={{ marginLeft: 20 }}>
<input
type="radio"
value="document"
checked={category === 'document'}
onChange={() => setCategory('document')}
/>
ເອກະສານ (ສູງສຸດ 10MB)
</label>
</div>

<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>
ວາງ{category === 'image' ? 'ຮູບພາບ' : 'ເອກະສານ'}ທີ່ນີ້
</p>
</div>
</div>
);
}

ການສະແກນ Virus/Malware

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

function MalwareScanUploader() {
const { files, state, actions, getDropProps, getInputProps } = useDropup({
customRules: [
// ສະແກນໄຟລ໌ກັບບໍລິການພາຍນອກ
async (file) => {
// ອັບໂຫຼດໄປບໍລິການສະແກນ virus
const formData = new FormData();
formData.append('file', file);

try {
const response = await fetch('/api/scan', {
method: 'POST',
body: formData,
});

const { safe, threat } = await response.json();

if (!safe) {
return `ກວດພົບ Malware: ${threat}`;
}

return true;
} catch (error) {
return 'ບໍ່ສາມາດສະແກນໄຟລ໌ໄດ້. ກະລຸນາລອງໃໝ່.';
}
},
],

onValidationError: (errors) => {
errors.forEach(({ file, errors }) => {
console.error(`${file.name} ຖືກປະຕິເສດ:`, errors);
});
},
});

return (
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>ໄຟລ໌ຈະຖືກສະແກນຫາ malware ກ່ອນອັບໂຫຼດ</p>
</div>
);
}

ກົດລະບຽບການກວດສອບທີ່ສ້າງໄວ້ລ່ວງໜ້າ

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

function PrebuiltRulesUploader() {
const { files, getDropProps, getInputProps } = useDropup({
customRules: [
// ກົດທີ່ສ້າງໄວ້
commonRules.noExecutables, // ບລັອກ .exe, .bat, ແລະອື່ນໆ
commonRules.noHiddenFiles, // ບລັອກໄຟລ໌ທີ່ເລີ່ມດ້ວຍ .
commonRules.maxFilenameLength(50), // ສູງສຸດ 50 ຕົວອັກສອນ
commonRules.allowedExtensions(['.jpg', '.png', '.pdf']),

// ລວມກັບກົດແບບກຳນົດເອງ
(file) => {
if (file.name.toLowerCase().includes('temp')) {
return 'ໄຟລ໌ຊົ່ວຄາວບໍ່ອະນຸຍາດ';
}
return true;
},
],
});

return (
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>ການກວດສອບໄຟລ໌ຢ່າງເຂັ້ມງວດຖືກເປີດໃຊ້ງານ</p>
</div>
);
}

ການສະແດງຂໍ້ຜິດພາດການກວດສອບ

import { useDropup } from '@samithahansaka/dropup';
import { useState } from 'react';

type ValidationErrorType = { file: File; errors: string[] };

function ValidationErrorDisplay() {
const [validationErrors, setValidationErrors] = useState<ValidationErrorType[]>([]);

const { files, getDropProps, getInputProps } = useDropup({
accept: 'image/*',
maxSize: 5 * 1024 * 1024,
maxFiles: 3,

customRules: [
(file) => {
if (file.name.length > 50) {
return 'ຊື່ໄຟລ໌ຍາວເກີນໄປ (ສູງສຸດ 50 ຕົວອັກສອນ)';
}
return true;
},
],

onValidationError: (errors) => {
setValidationErrors(errors);

// ລ້າງຫຼັງ 5 ວິນາທີ
setTimeout(() => setValidationErrors([]), 5000);
},
});

return (
<div>
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>ວາງຮູບພາບສູງສຸດ 3 ຮູບ (ສູງສຸດ 5MB ຕໍ່ອັນ)</p>
</div>

{/* ຂໍ້ຜິດພາດການກວດສອບ */}
{validationErrors.length > 0 && (
<div style={styles.errorContainer}>
<h4 style={styles.errorTitle}>ບາງໄຟລ໌ຖືກປະຕິເສດ:</h4>
{validationErrors.map(({ file, errors }, index) => (
<div key={index} style={styles.errorItem}>
<strong>{file.name}</strong>
<ul style={styles.errorList}>
{errors.map((error, i) => (
<li key={i}>{error}</li>
))}
</ul>
</div>
))}
</div>
)}

{/* ໄຟລ໌ທີ່ຍອມຮັບ */}
{files.length > 0 && (
<div style={styles.acceptedFiles}>
<h4>ໄຟລ໌ທີ່ຍອມຮັບ:</h4>
{files.map(file => (
<div key={file.id}>{file.name}</div>
))}
</div>
)}
</div>
);
}

const styles = {
dropzone: {
border: '2px dashed #ccc',
borderRadius: 8,
padding: 40,
textAlign: 'center' as const,
},
errorContainer: {
marginTop: 16,
padding: 16,
backgroundColor: '#ffebee',
borderRadius: 8,
border: '1px solid #f44336',
},
errorTitle: {
color: '#c62828',
margin: '0 0 12px',
},
errorItem: {
marginBottom: 8,
},
errorList: {
margin: '4px 0 0',
paddingLeft: 20,
color: '#c62828',
},
acceptedFiles: {
marginTop: 16,
padding: 16,
backgroundColor: '#e8f5e9',
borderRadius: 8,
},
};