檔案驗證
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, // 最大 10MB
minSize: 1024, // 最小 1KB
});
檔案數量限制
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, // 10MB
minSize: 100, // 100 bytes(防止空檔案)
// 數量限制
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,最大 10MB)</p>
)}
</div>
);
}