// @/resources/js/downloadService.js import { apiClient } from '@/resources/api/index'; import uploadProgressStore from '@/resources/js/uploadProgressStore'; // 파일 다운로드를 처리하는 서비스 const downloadService = { // 내부 타이머 변수 _simulationTimer: null, // 마지막 시뮬레이션 진행률 _lastSimulatedProgress: 0, // 진행률 시뮬레이션 시작 (서버 응답이 지연될 때) _startProgressSimulation() { // 이미 타이머가 있으면 정리 if (this._simulationTimer) { clearInterval(this._simulationTimer); } // 현재 진행률 저장 this._lastSimulatedProgress = uploadProgressStore.totalProgress; // 시작 진행률 설정 (최소 5%) if (this._lastSimulatedProgress < 5) { this._lastSimulatedProgress = 5; uploadProgressStore.totalProgress = 5; } // 진행률 시뮬레이션 시작 (최대 40%까지만) let simulatedProgress = this._lastSimulatedProgress; this._simulationTimer = setInterval(() => { // 실제 진행이 시작되면 시뮬레이션 중단 if (uploadProgressStore.totalProgress > simulatedProgress) { this._lastSimulatedProgress = uploadProgressStore.totalProgress; clearInterval(this._simulationTimer); this._simulationTimer = null; return; } // 진행률 증가 (40%까지) if (simulatedProgress < 40) { simulatedProgress += Math.random() * 1.5; // 0~1.5% 랜덤하게 증가 uploadProgressStore.totalProgress = Math.round(simulatedProgress); this._lastSimulatedProgress = uploadProgressStore.totalProgress; } }, 200); // 0.2초마다 업데이트 }, // 시뮬레이션 종료 _stopProgressSimulation() { if (this._simulationTimer) { clearInterval(this._simulationTimer); this._simulationTimer = null; } }, // 단일 파일 다운로드 메서드 async downloadFile(file, options = {}) { try { // 다운로드 상태 초기화 (현재 진행률 유지) const currentProgress = uploadProgressStore.totalProgress; uploadProgressStore.startDownload(file.fileNm || '파일 다운로드 중...'); uploadProgressStore.setStage('downloading'); // 이전 진행률이 있으면 유지 if (currentProgress > 0) { uploadProgressStore.totalProgress = currentProgress; } // 즉시 진행률 시뮬레이션 시작 (서버 응답 전) this._startProgressSimulation(); // apiClient를 사용하여 다운로드 요청 const response = await apiClient.get(`/file/${file.fileId}/${file.fileOrdr || 1}/fileDownload.json`, { responseType: 'blob', ...options, onDownloadProgress: (progressEvent) => { // 시뮬레이션 중단 this._stopProgressSimulation(); if (progressEvent.total) { // 진행 상태 계산 const realProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total); // 실제 진행률이 시뮬레이션 진행률보다 낮으면, 시뮬레이션 진행률부터 시작 const startProgress = Math.max(this._lastSimulatedProgress, realProgress); // 남은 진행률을 60%~100% 범위로 매핑 // 예: 실제 진행률이 0%일 때 40%, 100%일 때 100%가 되도록 const adjustedProgress = 40 + (realProgress * 60 / 100); // 둘 중 더 큰 값을 사용 uploadProgressStore.totalProgress = Math.round(Math.max(startProgress, adjustedProgress)); } // 사용자 정의 onDownloadProgress 콜백이 있으면 호출 if (options.onDownloadProgress) { options.onDownloadProgress(progressEvent); } } }); // 시뮬레이션 중단 (만약 아직 실행 중이라면) this._stopProgressSimulation(); // 다운로드 완료 표시 uploadProgressStore.totalProgress = 100; // 잠시 후 응답 반환 (완료 상태를 보여줄 시간 제공) await new Promise(resolve => setTimeout(resolve, 300)); return response; } catch (error) { // 시뮬레이션 중단 this._stopProgressSimulation(); // 오류 발생 시 상태 초기화 uploadProgressStore.handleError(); throw error; } }, // 다중 파일 다운로드 메서드 async downloadMultipleFiles(files, options = {}) { try { // 다운로드 상태 초기화 (현재 진행률 유지) const currentProgress = uploadProgressStore.totalProgress; uploadProgressStore.startDownload('다중 파일 다운로드 중...'); uploadProgressStore.setStage('downloading'); // 이전 진행률이 있으면 유지 if (currentProgress > 0) { uploadProgressStore.totalProgress = currentProgress; } // 즉시 진행률 시뮬레이션 시작 (서버 응답 전) this._startProgressSimulation(); // apiClient를 사용하여 다운로드 요청 const response = await apiClient.post(`/file/multiFileDownload.json`, files, { responseType: 'blob', ...options, onDownloadProgress: (progressEvent) => { // 시뮬레이션 중단 this._stopProgressSimulation(); if (progressEvent.total) { // 진행 상태 계산 const realProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total); // 실제 진행률이 시뮬레이션 진행률보다 낮으면, 시뮬레이션 진행률부터 시작 const startProgress = Math.max(this._lastSimulatedProgress, realProgress); // 남은 진행률을 40%~100% 범위로 매핑 // 예: 실제 진행률이 0%일 때 40%, 100%일 때 100%가 되도록 const adjustedProgress = 40 + (realProgress * 60 / 100); // 둘 중 더 큰 값을 사용 uploadProgressStore.totalProgress = Math.round(Math.max(startProgress, adjustedProgress)); } // 사용자 정의 onDownloadProgress 콜백이 있으면 호출 if (options.onDownloadProgress) { options.onDownloadProgress(progressEvent); } } }); // 시뮬레이션 중단 (만약 아직 실행 중이라면) this._stopProgressSimulation(); // 다운로드 완료 표시 uploadProgressStore.totalProgress = 100; // 잠시 후 응답 반환 (완료 상태를 보여줄 시간 제공) await new Promise(resolve => setTimeout(resolve, 300)); return response; } catch (error) { // 시뮬레이션 중단 this._stopProgressSimulation(); // 오류 발생 시 상태 초기화 uploadProgressStore.handleError(); throw error; } } }; export default downloadService;