diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 00:17:56 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 00:17:56 +0000 |
| commit | 9e280704988fdeffa05c1d8cbb731722f666c6af (patch) | |
| tree | bbf57b3c882502dc7afd2ff770d95aca69fca0d9 /app/api/vendor-investigations | |
| parent | 44356f1b203da5169db42950a42a8146f612c674 (diff) | |
(대표님) 앱 라우터 api 파트 커밋
Diffstat (limited to 'app/api/vendor-investigations')
| -rw-r--r-- | app/api/vendor-investigations/[investigationId]/attachments/route.ts | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/app/api/vendor-investigations/[investigationId]/attachments/route.ts b/app/api/vendor-investigations/[investigationId]/attachments/route.ts new file mode 100644 index 00000000..80513e28 --- /dev/null +++ b/app/api/vendor-investigations/[investigationId]/attachments/route.ts @@ -0,0 +1,158 @@ +// app/api/vendor-investigations/[investigationId]/attachments/route.ts +import { NextRequest, NextResponse } from "next/server" +import { promises as fs } from "fs" +import path from "path" +import { v4 as uuidv4 } from "uuid" +import db from "@/db/db" +import { vendorInvestigationAttachments } from "@/db/schema" +import { eq } from "drizzle-orm"; + +export async function POST( + req: NextRequest, + { params }: { params: { investigationId: string } } +) { + try { + const investigationId = parseInt(params.investigationId) + if (!investigationId) { + return NextResponse.json({ error: "Invalid investigation ID" }, { status: 400 }) + } + + const formData = await req.formData() + const file = formData.get("file") as File + + if (!file || file.size === 0) { + return NextResponse.json({ error: "No file provided" }, { status: 400 }) + } + + // 파일 크기 제한 (10MB) + const maxSize = 10 * 1024 * 1024 + if (file.size > maxSize) { + return NextResponse.json({ + error: `파일 크기가 ${maxSize / 1024 / 1024}MB를 초과합니다.` + }, { status: 400 }) + } + + // 지원하는 파일 타입 검증 + const allowedTypes = [ + 'application/pdf', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'image/png', + 'image/jpeg', + 'image/jpg', + 'image/gif' + ] + + if (!allowedTypes.includes(file.type)) { + return NextResponse.json({ + error: "지원하지 않는 파일 형식입니다." + }, { status: 400 }) + } + + // 파일 저장 + const arrayBuffer = await file.arrayBuffer() + const buffer = Buffer.from(arrayBuffer) + + // 고유한 파일명 생성 + const ext = path.extname(file.name) + const uniqueName = `${uuidv4()}${ext}` + + // 업로드 디렉토리 생성 + const uploadDir = path.join(process.cwd(), "public", "vendor-investigation", String(investigationId)) + await fs.mkdir(uploadDir, { recursive: true }) + + const filePath = path.join(uploadDir, uniqueName) + await fs.writeFile(filePath, buffer) + + // 파일 타입 결정 + let attachmentType = "OTHER" + if (file.type.includes("pdf")) { + attachmentType = "REPORT" + } else if (file.type.includes("image")) { + attachmentType = "PHOTO" + } else if ( + file.type.includes("word") || + file.type.includes("document") || + file.name.toLowerCase().includes("report") + ) { + attachmentType = "DOCUMENT" + } + + // DB에 파일 정보 저장 + const [attachment] = await db.insert(vendorInvestigationAttachments).values({ + investigationId, + fileName: file.name, + filePath: `/vendor-investigation/${investigationId}/${uniqueName}`, + fileSize: file.size, + mimeType: file.type, + attachmentType: attachmentType as "REPORT" | "PHOTO" | "DOCUMENT" | "CERTIFICATE" | "OTHER", + // uploadedBy: currentUserId, // 실제 사용자 ID로 설정 + }).returning() + + return NextResponse.json({ + success: true, + attachment: { + id: attachment.id, + fileName: attachment.fileName, + filePath: attachment.filePath, + fileSize: attachment.fileSize, + attachmentType: attachment.attachmentType + } + }) + + } catch (error) { + console.error("파일 업로드 오류:", error) + return NextResponse.json({ + error: "파일 업로드 중 오류가 발생했습니다." + }, { status: 500 }) + } +} + +// 첨부파일 삭제 +export async function DELETE( + req: NextRequest, + { params }: { params: { investigationId: string } } +) { + try { + const { searchParams } = new URL(req.url) + const attachmentId = searchParams.get("attachmentId") + + if (!attachmentId) { + return NextResponse.json({ error: "Attachment ID required" }, { status: 400 }) + } + + // DB에서 파일 정보 조회 + const attachment = await db.query.vendorInvestigationAttachments.findFirst({ + where: (attachments, { eq, and }) => and( + eq(attachments.id, parseInt(attachmentId)), + eq(attachments.investigationId, parseInt(params.investigationId)) + ) + }) + + if (!attachment) { + return NextResponse.json({ error: "Attachment not found" }, { status: 404 }) + } + + // 실제 파일 삭제 + const fullPath = path.join(process.cwd(), "public", attachment.filePath) + try { + await fs.unlink(fullPath) + } catch (error) { + console.warn("파일 삭제 실패 (파일이 존재하지 않을 수 있음):", error) + } + + // DB에서 레코드 삭제 + await db.delete(vendorInvestigationAttachments) + .where(eq(vendorInvestigationAttachments.id, parseInt(attachmentId))) + + return NextResponse.json({ success: true }) + + } catch (error) { + console.error("파일 삭제 오류:", error) + return NextResponse.json({ + error: "파일 삭제 중 오류가 발생했습니다." + }, { status: 500 }) + } +}
\ No newline at end of file |
