이미지 파일 업로드 기능
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import { randomUUID } from "crypto";
|
||||
import { PrismaClient } from "@/generated/prisma/client";
|
||||
|
||||
// 업로드된 이미지 파일을 저장할 디렉터리 (프로젝트 루트 기준)
|
||||
const UPLOAD_DIR = path.join(process.cwd(), "uploads");
|
||||
|
||||
let prisma: PrismaClient | null = null;
|
||||
try {
|
||||
prisma = new PrismaClient();
|
||||
} catch (error) {
|
||||
// DB 가 준비되지 않은 개발/테스트 환경에서도 업로드 자체는 동작할 수 있도록,
|
||||
// Prisma 초기화 실패는 치명적 오류로 취급하지 않고 로그만 남긴다.
|
||||
console.error("PrismaClient 초기화 실패 - 파일 시스템 전용 모드로 동작합니다.", error);
|
||||
prisma = null;
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const formData = await request.formData();
|
||||
const file = formData.get("file");
|
||||
|
||||
if (!file || typeof (file as any).arrayBuffer !== "function") {
|
||||
return NextResponse.json({ message: "file 필드는 필수입니다." }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.mkdir(UPLOAD_DIR, { recursive: true });
|
||||
} catch (error) {
|
||||
console.error("업로드 디렉터리 생성 실패", error);
|
||||
return NextResponse.json({ message: "업로드 디렉터리를 생성할 수 없습니다." }, { status: 500 });
|
||||
}
|
||||
|
||||
try {
|
||||
const arrayBuffer = await (file as any).arrayBuffer();
|
||||
const bytes = new Uint8Array(arrayBuffer);
|
||||
const id = randomUUID();
|
||||
|
||||
// 파일 경로는 uploads/<id> 형태로 저장한다.
|
||||
const relativePath = path.join("uploads", id);
|
||||
const filePath = path.join(process.cwd(), relativePath);
|
||||
|
||||
await fs.writeFile(filePath, bytes);
|
||||
|
||||
// 가능하다면 Asset 테이블에도 메타데이터를 남긴다.
|
||||
if (prisma) {
|
||||
try {
|
||||
const project = await prisma.project.upsert({
|
||||
where: { slug: "assets-global" },
|
||||
update: {},
|
||||
create: {
|
||||
id: randomUUID(),
|
||||
title: "Assets Global",
|
||||
slug: "assets-global",
|
||||
contentJson: [],
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.asset.create({
|
||||
data: {
|
||||
id,
|
||||
projectId: project.id,
|
||||
kind: "image",
|
||||
url: relativePath,
|
||||
meta: {
|
||||
sourceType: "uploaded",
|
||||
originalName: (file as any).name ?? "upload",
|
||||
mimeType: (file as any).type ?? "application/octet-stream",
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("이미지 Asset DB 저장 실패 - 파일 시스템만 사용합니다.", error);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
id,
|
||||
servedUrl: `/api/image/${id}`,
|
||||
},
|
||||
{ status: 201 },
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("이미지 업로드 처리 중 오류", error);
|
||||
return NextResponse.json({ message: "이미지 업로드 중 오류가 발생했습니다." }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user