파일 유효성 검사
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 바이트 (빈 파일 방지)
// 개수 제한
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>
);
}