diff options
Diffstat (limited to 'lib/dolce/utils/upload-with-progress.ts')
| -rw-r--r-- | lib/dolce/utils/upload-with-progress.ts | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/lib/dolce/utils/upload-with-progress.ts b/lib/dolce/utils/upload-with-progress.ts index 8e36afe4..c86ed8a0 100644 --- a/lib/dolce/utils/upload-with-progress.ts +++ b/lib/dolce/utils/upload-with-progress.ts @@ -40,24 +40,31 @@ export async function uploadFilesWithProgress({ }); const xhr = new XMLHttpRequest(); + + // 타임아웃 설정 (1시간) + xhr.timeout = 3600000; // 1시간 (밀리초) - // 전체 업로드 진행도 (단순화: 전체 진행도를 각 파일에 분배) + // 전체 업로드 진행도 + // 주의: xhr.upload.progress는 클라이언트→서버 전송만 추적 + // 서버에서 DOLCE API로 재업로드하는 과정은 별도 (Node.js fetch는 업로드 진행도 추적 미지원) + // → UI에서 90% 이상일 때 "서버에서 DOLCE API로 전송 중..." 메시지 표시 xhr.upload.addEventListener("progress", (event) => { if (event.lengthComputable) { - const totalProgress = (event.loaded / event.total) * 100; + // 전송 완료 = 서버에 도착 (실제 DOLCE API 업로드 시작) + // 서버 처리를 위해 최대 95%까지만 표시 (나머지 5%는 서버→DOLCE 업로드) + const totalProgress = Math.min((event.loaded / event.total) * 95, 95); // 현재 업로드 중인 파일 인덱스 추정 - const filesCompleted = Math.floor((totalProgress / 100) * files.length); + const filesCompleted = Math.floor((totalProgress / 95) * files.length); const currentFileIndex = Math.min(filesCompleted, files.length - 1); // 각 파일별 진행도 계산 files.forEach((_, index) => { if (index < filesCompleted) { - callbacks.onProgress(index, 100); - callbacks.onFileComplete(index); + callbacks.onProgress(index, 95); } else if (index === currentFileIndex) { - const fileProgress = ((totalProgress / 100) * files.length - filesCompleted) * 100; - callbacks.onProgress(index, Math.min(fileProgress, 99)); + const fileProgress = ((totalProgress / 95) * files.length - filesCompleted) * 95; + callbacks.onProgress(index, Math.min(fileProgress, 94)); } else { callbacks.onProgress(index, 0); } @@ -70,15 +77,35 @@ export async function uploadFilesWithProgress({ try { const response = JSON.parse(xhr.responseText); - // 모든 파일 완료 처리 - files.forEach((_, index) => { - callbacks.onProgress(index, 100); - callbacks.onFileComplete(index); - }); + // 서버 응답 검증 + if (response.success) { + console.log(`[업로드 클라이언트] 서버 처리 완료: ${response.uploadedCount}개 파일`); + + // 서버에서 실제 처리 완료 시에만 100% + files.forEach((_, index) => { + callbacks.onProgress(index, 100); + callbacks.onFileComplete(index); + }); - resolve(response); + resolve(response); + } else { + // 서버에서 에러 응답 + const errorMsg = response.error || "서버에서 업로드 실패"; + console.error(`[업로드 클라이언트] 서버 에러:`, errorMsg); + + files.forEach((_, index) => { + callbacks.onFileError(index, errorMsg); + }); + + resolve({ + success: false, + error: errorMsg, + }); + } } catch (error) { - const errorMsg = "응답 파싱 실패"; + const errorMsg = `응답 파싱 실패: ${xhr.responseText?.substring(0, 100)}`; + console.error(`[업로드 클라이언트] 파싱 에러:`, error, xhr.responseText); + files.forEach((_, index) => { callbacks.onFileError(index, errorMsg); }); @@ -89,6 +116,8 @@ export async function uploadFilesWithProgress({ } } else { const errorMsg = `업로드 실패: ${xhr.status} ${xhr.statusText}`; + console.error(`[업로드 클라이언트] HTTP 에러:`, errorMsg, xhr.responseText); + files.forEach((_, index) => { callbacks.onFileError(index, errorMsg); }); @@ -101,6 +130,8 @@ export async function uploadFilesWithProgress({ xhr.addEventListener("error", () => { const errorMsg = "네트워크 오류"; + console.error(`[업로드 클라이언트] 네트워크 에러`); + files.forEach((_, index) => { callbacks.onFileError(index, errorMsg); }); @@ -112,6 +143,21 @@ export async function uploadFilesWithProgress({ xhr.addEventListener("abort", () => { const errorMsg = "업로드가 취소되었습니다"; + console.warn(`[업로드 클라이언트] 업로드 취소됨`); + + files.forEach((_, index) => { + callbacks.onFileError(index, errorMsg); + }); + resolve({ + success: false, + error: errorMsg, + }); + }); + + xhr.addEventListener("timeout", () => { + const errorMsg = "업로드 타임아웃 (1시간 초과)"; + console.error(`[업로드 클라이언트] 타임아웃 발생 (1시간 초과)`); + files.forEach((_, index) => { callbacks.onFileError(index, errorMsg); }); @@ -121,6 +167,7 @@ export async function uploadFilesWithProgress({ }); }); + console.log(`[업로드 클라이언트] 시작: ${files.length}개 파일`); xhr.open("POST", "/api/dolce/upload-files"); xhr.send(formData); }); |
