summaryrefslogtreecommitdiff
path: root/app/api/compliance/files/download
diff options
context:
space:
mode:
Diffstat (limited to 'app/api/compliance/files/download')
-rw-r--r--app/api/compliance/files/download/route.ts90
1 files changed, 90 insertions, 0 deletions
diff --git a/app/api/compliance/files/download/route.ts b/app/api/compliance/files/download/route.ts
new file mode 100644
index 00000000..7bcb59cd
--- /dev/null
+++ b/app/api/compliance/files/download/route.ts
@@ -0,0 +1,90 @@
+import { NextRequest, NextResponse } from "next/server";
+import { getServerSession } from "next-auth";
+import { authOptions } from "@/lib/auth";
+import db from "@/db/db";
+import { complianceResponseFiles } from "@/db/schema/compliance";
+import { eq } from "drizzle-orm";
+import fs from "fs/promises";
+import path from "path";
+
+// MIME 타입 매핑 (기존 API와 동일)
+const getMimeType = (filePath: string): string => {
+ const ext = path.extname(filePath).toLowerCase();
+ const mimeTypes: Record<string, string> = {
+ '.pdf': 'application/pdf',
+ '.doc': 'application/msword',
+ '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ '.xls': 'application/vnd.ms-excel',
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ '.jpg': 'image/jpeg',
+ '.jpeg': 'image/jpeg',
+ '.png': 'image/png',
+ '.gif': 'image/gif',
+ '.txt': 'text/plain',
+ '.zip': 'application/zip',
+ };
+
+ return mimeTypes[ext] || 'application/octet-stream';
+};
+
+export async function GET(request: NextRequest) {
+ try {
+ // 인증 확인
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return NextResponse.json({ error: "인증이 필요합니다." }, { status: 401 });
+ }
+
+ // 쿼리 파라미터에서 fileId 추출
+ const { searchParams } = new URL(request.url);
+ const fileId = searchParams.get("fileId");
+
+ if (!fileId) {
+ return NextResponse.json({ error: "파일 ID가 필요합니다." }, { status: 400 });
+ }
+
+ // 파일 정보 조회
+ const [file] = await db
+ .select()
+ .from(complianceResponseFiles)
+ .where(eq(complianceResponseFiles.id, parseInt(fileId)));
+
+ if (!file) {
+ return NextResponse.json({ error: "파일을 찾을 수 없습니다." }, { status: 404 });
+ }
+
+ // 파일 경로 구성 (public 폴더 기준)
+ const filePath = path.join(process.cwd(), "public", file.filePath);
+
+ // 파일 존재 확인
+ try {
+ await fs.access(filePath);
+ } catch {
+ return NextResponse.json({ error: "파일이 서버에 존재하지 않습니다." }, { status: 404 });
+ }
+
+ // 파일 읽기
+ const fileBuffer = await fs.readFile(filePath);
+
+ // 파일 타입 결정
+ const mimeType = file.mimeType || getMimeType(file.filePath);
+
+ // 응답 헤더 설정
+ const headers = new Headers();
+ headers.set("Content-Type", mimeType);
+ headers.set("Content-Disposition", `attachment; filename="${encodeURIComponent(file.fileName)}"`);
+ headers.set("Content-Length", file.fileSize?.toString() || fileBuffer.length.toString());
+
+ return new NextResponse(fileBuffer, {
+ status: 200,
+ headers,
+ });
+
+ } catch (error) {
+ console.error("파일 다운로드 오류:", error);
+ return NextResponse.json(
+ { error: "파일 다운로드 중 오류가 발생했습니다." },
+ { status: 500 }
+ );
+ }
+}