92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { promises as fs } from "fs";
|
|
import path from "path";
|
|
import { randomUUID } from "crypto";
|
|
import { PrismaClient } from "@prisma/client";
|
|
|
|
// 업로드된 이미지 파일을 저장할 디렉터리 (프로젝트 루트 기준)
|
|
const UPLOAD_DIR = path.join(process.cwd(), "uploads");
|
|
|
|
let prisma: PrismaClient | null = null;
|
|
if (process.env.DATABASE_URL && process.env.DATABASE_URL.trim() !== "") {
|
|
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 });
|
|
}
|
|
}
|