summaryrefslogtreecommitdiff
path: root/app/api/tbe-download/route.ts
diff options
context:
space:
mode:
authorrlaks5757 <rlaks5757@gmail.com>2025-03-27 17:48:36 +0900
committerrlaks5757 <rlaks5757@gmail.com>2025-03-27 17:48:36 +0900
commit773918229ccb14c0d00798fbbf2b2be0130a8251 (patch)
treeab9e200e65cc471ec139cd8482bde70a3b0a105f /app/api/tbe-download/route.ts
parent92ddb4f13d48cbf344dc2bf63df4457b3c713608 (diff)
parent34bbeb86c1a8d24b5f526710889b5e54d699cfd0 (diff)
merge complete
Diffstat (limited to 'app/api/tbe-download/route.ts')
-rw-r--r--app/api/tbe-download/route.ts121
1 files changed, 121 insertions, 0 deletions
diff --git a/app/api/tbe-download/route.ts b/app/api/tbe-download/route.ts
new file mode 100644
index 00000000..12e42920
--- /dev/null
+++ b/app/api/tbe-download/route.ts
@@ -0,0 +1,121 @@
+// app/api/rfq-download/route.ts
+import { NextRequest, NextResponse } from 'next/server';
+import { readFile, access, constants } from 'fs/promises';
+import { join } from 'path';
+import db from '@/db/db';
+import { rfqAttachments, vendorResponseAttachments } from '@/db/schema/rfq';
+import { eq } from 'drizzle-orm';
+
+export async function GET(request: NextRequest) {
+ try {
+ // 파일 경로 파라미터 받기
+ const path = request.nextUrl.searchParams.get("path");
+
+ if (!path) {
+ return NextResponse.json(
+ { error: "File path is required" },
+ { status: 400 }
+ );
+ }
+
+ // DB에서 파일 정보 조회 (정확히 일치하는 filePath로 검색)
+ const [dbRecord] = await db
+ .select({
+ fileName: vendorResponseAttachments.fileName,
+ filePath: vendorResponseAttachments.filePath
+ })
+ .from(vendorResponseAttachments)
+ .where(eq(vendorResponseAttachments.filePath, path));
+
+ // 파일 정보 설정
+ let fileName;
+
+ if (dbRecord) {
+ // DB에서 찾은 경우 원본 파일명 사용
+ fileName = dbRecord.fileName;
+ console.log("DB에서 원본 파일명 찾음:", fileName);
+ } else {
+ // DB에서 찾지 못한 경우 경로에서 파일명 추출
+ fileName = path.split('/').pop() || 'download';
+ }
+
+ // 파일 경로 구성
+ const storedPath = path.replace(/^\/+/, ""); // 앞쪽 슬래시 제거
+
+ // 파일 경로 시도
+ const possiblePaths = [
+ join(process.cwd(), "public", storedPath)
+ ];
+
+ // 실제 파일 찾기
+ let actualPath = null;
+ for (const testPath of possiblePaths) {
+ try {
+ await access(testPath, constants.R_OK);
+ actualPath = testPath;
+ break;
+ } catch (err) {
+ console.log("❌ 경로에 파일 없음:", testPath);
+ }
+ }
+
+ if (!actualPath) {
+ return NextResponse.json(
+ {
+ error: "File not found on server",
+ details: {
+ path: path,
+ triedPaths: possiblePaths
+ }
+ },
+ { status: 404 }
+ );
+ }
+
+ const fileBuffer = await readFile(actualPath);
+
+ // MIME 타입 결정
+ const fileExtension = fileName.split('.').pop()?.toLowerCase() || '';
+
+ let contentType = 'application/octet-stream'; // 기본 바이너리
+
+ // 확장자에 따른 MIME 타입 매핑
+ 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',
+ 'ppt': 'application/vnd.ms-powerpoint',
+ 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'txt': 'text/plain',
+ 'csv': 'text/csv',
+ 'png': 'image/png',
+ 'jpg': 'image/jpeg',
+ 'jpeg': 'image/jpeg',
+ 'gif': 'image/gif',
+ };
+
+ contentType = mimeTypes[fileExtension] || contentType;
+
+ // 다운로드용 헤더 설정
+ const headers = new Headers();
+ headers.set('Content-Type', contentType);
+ headers.set('Content-Disposition', `attachment; filename="${encodeURIComponent(fileName)}"`);
+ headers.set('Content-Length', fileBuffer.length.toString());
+
+ return new NextResponse(fileBuffer, {
+ status: 200,
+ headers,
+ });
+ } catch (error) {
+ console.error('❌ RFQ 파일 다운로드 오류:', error);
+ return NextResponse.json(
+ {
+ error: 'Failed to download file',
+ details: String(error)
+ },
+ { status: 500 }
+ );
+ }
+} \ No newline at end of file