summaryrefslogtreecommitdiff
path: root/lib/dolce/utils/upload-with-progress.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-24 15:38:35 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-24 15:38:35 +0900
commitaf813883db9bae24755e05205647954fd0ab1270 (patch)
tree79c963774ede6238bd878a22d8baba2ce5c02764 /lib/dolce/utils/upload-with-progress.ts
parenta55198e00ff982f6310a08c76a0502c90dd7d859 (diff)
(김준회) dolce 파일업로드 개선 및 nginx conf 수정(커밋관리X)
Diffstat (limited to 'lib/dolce/utils/upload-with-progress.ts')
-rw-r--r--lib/dolce/utils/upload-with-progress.ts74
1 files changed, 60 insertions, 14 deletions
diff --git a/lib/dolce/utils/upload-with-progress.ts b/lib/dolce/utils/upload-with-progress.ts
index 8e36afe4..1204bf36 100644
--- a/lib/dolce/utils/upload-with-progress.ts
+++ b/lib/dolce/utils/upload-with-progress.ts
@@ -40,24 +40,30 @@ export async function uploadFilesWithProgress({
});
const xhr = new XMLHttpRequest();
+
+ // 타임아웃 설정 (1시간)
+ xhr.timeout = 3600000; // 1시간 (밀리초)
- // 전체 업로드 진행도 (단순화: 전체 진행도를 각 파일에 분배)
+ // 전체 업로드 진행도
+ // 주의: xhr.upload.progress는 클라이언트→서버 전송만 추적
+ // 서버에서 DOLCE API로 재업로드하는 과정은 별도 (추적 불가)
xhr.upload.addEventListener("progress", (event) => {
if (event.lengthComputable) {
- const totalProgress = (event.loaded / event.total) * 100;
+ // 전송 완료 = 서버에 도착 (실제 처리 시작)
+ // 서버 처리를 위해 최대 95%까지만 표시
+ 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 +76,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 +115,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 +129,8 @@ export async function uploadFilesWithProgress({
xhr.addEventListener("error", () => {
const errorMsg = "네트워크 오류";
+ console.error(`[업로드 클라이언트] 네트워크 에러`);
+
files.forEach((_, index) => {
callbacks.onFileError(index, errorMsg);
});
@@ -112,6 +142,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 +166,7 @@ export async function uploadFilesWithProgress({
});
});
+ console.log(`[업로드 클라이언트] 시작: ${files.length}개 파일`);
xhr.open("POST", "/api/dolce/upload-files");
xhr.send(formData);
});