summaryrefslogtreecommitdiff
path: root/lib/downloadFile.ts
blob: e27779760fb927e84e5ee875ffec4b55cc95c45b (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
'use server'

import fs from 'fs/promises'
import path from 'path'
import { NextResponse } from 'next/server'

/**
 * 첨부 파일 다운로드를 위한 서버 액션
 * 
 * @param filePath 파일의 상대 경로
 * @returns 파일 내용(Base64 인코딩) 및 메타데이터를 포함한 객체
 */
export async function downloadFileAction(filePath: string) {
  try {
    // 보안: 파일 경로가 uploads 디렉토리 내에 있는지 확인
    if (!filePath.startsWith('/uploads/') && !filePath.startsWith('uploads/')) {
      return { 
        ok: false, 
        error: 'Invalid file path. Only files in the uploads directory can be downloaded.' 
      };
    }

    // 실제 서버 파일 시스템에서의 전체 경로 계산
    // 참고: process.cwd()는 현재 실행 중인 프로세스의 작업 디렉토리를 반환합니다.
    // 환경에 따라 public 폴더나 다른 위치를 기준으로 할 수도 있습니다.
    const normalizedPath = filePath.startsWith('/') ? filePath.slice(1) : filePath;
    const fullPath = path.join(process.cwd(), 'public', normalizedPath);

    // 파일 존재 여부 확인
    try {
      await fs.access(fullPath);
    } catch {
      return { ok: false, error: 'File not found' };
    }

    // 파일 읽기
    const fileBuffer = await fs.readFile(fullPath);
    
    // 파일 통계 정보 가져오기
    const stats = await fs.stat(fullPath);
    
    // MIME 타입 추측
    const extension = path.extname(fullPath).toLowerCase();
    let mimeType = 'application/octet-stream'; // 기본값
    
    // 일반적인 파일 타입에 대한 MIME 타입 매핑
    const mimeTypes = {
      '.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',
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.jpeg': 'image/jpeg',
      '.gif': 'image/gif',
      '.txt': 'text/plain',
    };
    
    if (extension in mimeTypes) {
      mimeType = mimeTypes[extension];
    }
    
    // Base64로 인코딩하여 반환
    return {
      ok: true,
      data: {
        content: fileBuffer.toString('base64'),
        fileName: path.basename(fullPath),
        size: stats.size,
        mimeType,
      },
    };
  } catch (error) {
    console.error('Download error:', error);
    return { 
      ok: false, 
      error: error instanceof Error ? error.message : 'An unknown error occurred' 
    };
  }
}