summaryrefslogtreecommitdiff
path: root/lib/downloadFile.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/downloadFile.ts')
-rw-r--r--lib/downloadFile.ts81
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/downloadFile.ts b/lib/downloadFile.ts
new file mode 100644
index 00000000..e2777976
--- /dev/null
+++ b/lib/downloadFile.ts
@@ -0,0 +1,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'
+ };
+ }
+} \ No newline at end of file