From b4d2a08de7b2750363c91966b734b51917e11c65 Mon Sep 17 00:00:00 2001 From: koreacomp5 Date: Thu, 9 Oct 2025 17:51:05 +0900 Subject: [PATCH] =?UTF-8?q?9.2=20=EC=9D=B4=EB=AF=B8=EC=A7=80/=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20=EA=B2=80=EC=A6=9D=20o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/uploads/route.ts | 19 ++++++++++++++++++- todolist.txt | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/app/api/uploads/route.ts b/src/app/api/uploads/route.ts index 9cf5e5c..501db79 100644 --- a/src/app/api/uploads/route.ts +++ b/src/app/api/uploads/route.ts @@ -9,9 +9,26 @@ export async function POST(req: Request) { const file = form.get("file") as File | null; if (!file) return NextResponse.json({ error: "file required" }, { status: 400 }); + // 검증: 이미지 MIME 및 용량 제한(5MB) + const ALLOWED = new Set(["image/jpeg", "image/png", "image/webp", "image/gif"]); + const MAX_SIZE = 5 * 1024 * 1024; + const contentType = (file as any).type || ""; + if (!ALLOWED.has(contentType)) return NextResponse.json({ error: "invalid file type" }, { status: 400 }); const bytes = await file.arrayBuffer(); + if (bytes.byteLength > MAX_SIZE) return NextResponse.json({ error: "file too large" }, { status: 400 }); const buffer = Buffer.from(bytes); - const ext = path.extname(file.name || "") || ".bin"; + + // 확장자 결정 + const mimeToExt: Record = { + "image/jpeg": ".jpg", + "image/png": ".png", + "image/webp": ".webp", + "image/gif": ".gif", + }; + const inferredExt = mimeToExt[contentType] ?? ".bin"; + const nameExt = path.extname(file.name || ""); + const ext = nameExt && Object.values(mimeToExt).includes(nameExt.toLowerCase()) ? nameExt.toLowerCase() : inferredExt; + const uploadsDir = path.join(process.cwd(), "public", "uploads"); await fs.mkdir(uploadsDir, { recursive: true }); const filename = `${Date.now()}-${Math.random().toString(36).slice(2)}${ext}`; diff --git a/todolist.txt b/todolist.txt index b4a1a65..5fcb06e 100644 --- a/todolist.txt +++ b/todolist.txt @@ -63,7 +63,7 @@ [에디터/업로드] 9.1 에디터(Tiptap/Quill 중 택1) 통합 o -9.2 이미지/파일 업로드 서버 처리 및 검증 +9.2 이미지/파일 업로드 서버 처리 및 검증 o 9.3 리사이즈/웹포맷 최적화 및 용량 제한 9.4 붙여넣기/드래그 삽입, 캡션/대체텍스트 9.5 사진 중심 카테고리 프리셋(해상도/비율/워터마크 옵션)