summaryrefslogtreecommitdiff
path: root/components/ship-vendor-document
diff options
context:
space:
mode:
Diffstat (limited to 'components/ship-vendor-document')
-rw-r--r--components/ship-vendor-document/add-attachment-dialog.tsx55
-rw-r--r--components/ship-vendor-document/new-revision-dialog.tsx51
2 files changed, 100 insertions, 6 deletions
diff --git a/components/ship-vendor-document/add-attachment-dialog.tsx b/components/ship-vendor-document/add-attachment-dialog.tsx
index 6765bcf5..4a51c3b5 100644
--- a/components/ship-vendor-document/add-attachment-dialog.tsx
+++ b/components/ship-vendor-document/add-attachment-dialog.tsx
@@ -38,7 +38,7 @@ import { useSession } from "next-auth/react"
* -----------------------------------------------------------------------------------------------*/
// 파일 검증 스키마
-const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 50MB
+const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 1GB
const ACCEPTED_FILE_TYPES = [
'application/pdf',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
@@ -73,7 +73,7 @@ const attachmentUploadSchema = z.object({
// .max(10, "Maximum 10 files can be uploaded")
.refine(
(files) => files.every((file) => file.size <= MAX_FILE_SIZE),
- "File size must be 50MB or less"
+ "File size must be 1GB or less"
)
// .refine(
// (files) => files.every((file) => ACCEPTED_FILE_TYPES.includes(file.type)),
@@ -101,10 +101,46 @@ function FileUploadArea({
}) {
const fileInputRef = React.useRef<HTMLInputElement>(null)
+ // 파일 검증 함수
+ const validateFiles = (filesToValidate: File[]): { valid: File[], invalid: string[] } => {
+ const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 1GB
+ const FORBIDDEN_EXTENSIONS = ['exe', 'com', 'dll', 'vbs', 'js', 'asp', 'aspx', 'bat', 'cmd']
+
+ const valid: File[] = []
+ const invalid: string[] = []
+
+ filesToValidate.forEach(file => {
+ // 파일 크기 검증
+ if (file.size > MAX_FILE_SIZE) {
+ invalid.push(`${file.name}: 파일 크기가 1GB를 초과합니다 (${formatFileSize(file.size)})`)
+ return
+ }
+
+ // 파일 확장자 검증
+ const extension = file.name.split('.').pop()?.toLowerCase()
+ if (extension && FORBIDDEN_EXTENSIONS.includes(extension)) {
+ invalid.push(`${file.name}: 금지된 파일 형식입니다 (.${extension})`)
+ return
+ }
+
+ valid.push(file)
+ })
+
+ return { valid, invalid }
+ }
+
const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
const selectedFiles = Array.from(event.target.files || [])
if (selectedFiles.length > 0) {
- onFilesChange([...files, ...selectedFiles])
+ const { valid, invalid } = validateFiles(selectedFiles)
+
+ if (invalid.length > 0) {
+ invalid.forEach(msg => toast.error(msg))
+ }
+
+ if (valid.length > 0) {
+ onFilesChange([...files, ...valid])
+ }
}
}
@@ -112,7 +148,15 @@ function FileUploadArea({
event.preventDefault()
const droppedFiles = Array.from(event.dataTransfer.files)
if (droppedFiles.length > 0) {
- onFilesChange([...files, ...droppedFiles])
+ const { valid, invalid } = validateFiles(droppedFiles)
+
+ if (invalid.length > 0) {
+ invalid.forEach(msg => toast.error(msg))
+ }
+
+ if (valid.length > 0) {
+ onFilesChange([...files, ...valid])
+ }
}
}
@@ -147,6 +191,9 @@ function FileUploadArea({
<p className="text-xs text-muted-foreground">
Supports PDF, Word, Excel, Image, Text, ZIP, CAD files (DWG, DXF, STEP, STL, IGES) (max 1GB)
</p>
+ <p className="text-xs text-red-600 mt-1 font-medium">
+ Forbidden file types: .exe, .com, .dll, .vbs, .js, .asp, .aspx, .bat, .cmd
+ </p>
<p className="text-xs text-orange-600 mt-1">
Note: File names cannot contain these characters: &lt; &gt; : &quot; &apos; | ? *
</p>
diff --git a/components/ship-vendor-document/new-revision-dialog.tsx b/components/ship-vendor-document/new-revision-dialog.tsx
index 91694827..bdbb1bc6 100644
--- a/components/ship-vendor-document/new-revision-dialog.tsx
+++ b/components/ship-vendor-document/new-revision-dialog.tsx
@@ -83,10 +83,46 @@ function FileUploadArea({
}) {
const fileInputRef = React.useRef<HTMLInputElement>(null)
+ // 파일 검증 함수
+ const validateFiles = (filesToValidate: File[]): { valid: File[], invalid: string[] } => {
+ const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 1GB
+ const FORBIDDEN_EXTENSIONS = ['exe', 'com', 'dll', 'vbs', 'js', 'asp', 'aspx', 'bat', 'cmd']
+
+ const valid: File[] = []
+ const invalid: string[] = []
+
+ filesToValidate.forEach(file => {
+ // 파일 크기 검증
+ if (file.size > MAX_FILE_SIZE) {
+ invalid.push(`${file.name}: 파일 크기가 1GB를 초과합니다 (${formatFileSize(file.size)})`)
+ return
+ }
+
+ // 파일 확장자 검증
+ const extension = file.name.split('.').pop()?.toLowerCase()
+ if (extension && FORBIDDEN_EXTENSIONS.includes(extension)) {
+ invalid.push(`${file.name}: 금지된 파일 형식입니다 (.${extension})`)
+ return
+ }
+
+ valid.push(file)
+ })
+
+ return { valid, invalid }
+ }
+
const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
const selectedFiles = Array.from(event.target.files || [])
if (selectedFiles.length > 0) {
- onFilesChange([...files, ...selectedFiles])
+ const { valid, invalid } = validateFiles(selectedFiles)
+
+ if (invalid.length > 0) {
+ invalid.forEach(msg => toast.error(msg))
+ }
+
+ if (valid.length > 0) {
+ onFilesChange([...files, ...valid])
+ }
}
}
@@ -94,7 +130,15 @@ function FileUploadArea({
event.preventDefault()
const droppedFiles = Array.from(event.dataTransfer.files)
if (droppedFiles.length > 0) {
- onFilesChange([...files, ...droppedFiles])
+ const { valid, invalid } = validateFiles(droppedFiles)
+
+ if (invalid.length > 0) {
+ invalid.forEach(msg => toast.error(msg))
+ }
+
+ if (valid.length > 0) {
+ onFilesChange([...files, ...valid])
+ }
}
}
@@ -132,6 +176,9 @@ function FileUploadArea({
<p className="text-xs text-orange-600 mt-1">
Note: File names cannot contain these characters: &lt; &gt; : &quot; &apos; | ? *
</p>
+ <p className="text-xs text-red-600 mt-1 font-medium">
+ Forbidden file types: .exe, .com, .dll, .vbs, .js, .asp, .aspx, .bat, .cmd
+ </p>
<input
ref={fileInputRef}
type="file"