summaryrefslogtreecommitdiff
path: root/app/api/tbe-download/route.ts
blob: 12e4292028eec2efd049ec907eff4354785041ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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 }
    );
  }
}