import { NextRequest } from "next/server" import { join } from "path" import { readFile } from "fs/promises" export async function GET(request: NextRequest) { try { const searchParams = request.nextUrl.searchParams const filePath = searchParams.get("path") if (!filePath) { return new Response("File path is required", { status: 400 }) } // 보안: 경로 조작 방지 if (filePath.includes("..") || !filePath.startsWith("/techsales-rfq/")) { return new Response("Invalid file path", { status: 400 }) } // 파일 경로 구성 (public 폴더 기준) const fullPath = join(process.cwd(), "public", filePath) try { // 파일 읽기 const fileBuffer = await readFile(fullPath) // 파일명 추출 const fileName = filePath.split("/").pop() || "download" // MIME 타입 결정 const ext = fileName.split(".").pop()?.toLowerCase() let contentType = "application/octet-stream" switch (ext) { case "pdf": contentType = "application/pdf" break case "doc": contentType = "application/msword" break case "docx": contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" break case "xls": contentType = "application/vnd.ms-excel" break case "xlsx": contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" break case "jpg": case "jpeg": contentType = "image/jpeg" break case "png": contentType = "image/png" break case "gif": contentType = "image/gif" break case "txt": contentType = "text/plain" break case "zip": contentType = "application/zip" break default: contentType = "application/octet-stream" } // 응답 헤더 설정 const headers = new Headers({ "Content-Type": contentType, "Content-Disposition": `attachment; filename="${encodeURIComponent(fileName)}"`, "Content-Length": fileBuffer.length.toString(), }) return new Response(fileBuffer, { headers }) } catch (fileError) { console.error("File read error:", fileError) return new Response("File not found", { status: 404 }) } } catch (error) { console.error("Download error:", error) return new Response("Internal server error", { status: 500 }) } }