/** * 파일 다운로드 유틸리티 * * 백엔드 API: GET /api/v1/files/{id}/download * 프록시: GET /api/proxy/files/{id}/download */ /** * 파일 ID로 다운로드 * @param fileId 파일 ID * @param fileName 저장할 파일명 (선택, 없으면 서버에서 제공하는 이름 사용) */ export async function downloadFileById(fileId: number, fileName?: string): Promise { try { const response = await fetch(`/api/proxy/files/${fileId}/download`); if (!response.ok) { throw new Error(`다운로드 실패: ${response.status}`); } const blob = await response.blob(); // 파일명이 없으면 Content-Disposition 헤더에서 추출 시도 let downloadFileName = fileName; if (!downloadFileName) { const contentDisposition = response.headers.get('Content-Disposition'); if (contentDisposition) { const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/); if (match && match[1]) { downloadFileName = match[1].replace(/['"]/g, ''); // URL 디코딩 (한글 파일명 처리) try { downloadFileName = decodeURIComponent(downloadFileName); } catch { // 디코딩 실패 시 그대로 사용 } } } } // 그래도 없으면 기본 파일명 if (!downloadFileName) { downloadFileName = `file_${fileId}`; } // Blob URL 생성 및 다운로드 트리거 const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = downloadFileName; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch (error) { console.error('[fileDownload] 다운로드 오류:', error); throw error; } } /** * 파일 경로로 새 탭에서 열기 (미리보기용) * @param filePath 파일 경로 */ export function openFileInNewTab(filePath: string): void { // 백엔드 파일 서빙 URL 구성 const baseUrl = process.env.NEXT_PUBLIC_API_URL || ''; const fileUrl = `${baseUrl}/storage/${filePath}`; window.open(fileUrl, '_blank'); }