diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-26 18:43:10 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-26 18:43:10 +0900 |
| commit | 5a370de52d6947d35aa07f9545c4f6a4d83eadd7 (patch) | |
| tree | e66741491771ef941560c34e75b604c5f7dfc14f /lib/dolce-v2 | |
| parent | 8547034e6d82e4d1184f35af2dbff67180d89dc8 (diff) | |
(김준회) dolce 메모리 효율적 동기화 처리(Streaming), 로컬 건 Date 정보 formatting, Uploader 정보 네임 표시
Diffstat (limited to 'lib/dolce-v2')
| -rw-r--r-- | lib/dolce-v2/dialogs/add-and-modify-detail-drawing-dialog-v2.tsx | 131 | ||||
| -rw-r--r-- | lib/dolce-v2/sync-service.ts | 25 |
2 files changed, 20 insertions, 136 deletions
diff --git a/lib/dolce-v2/dialogs/add-and-modify-detail-drawing-dialog-v2.tsx b/lib/dolce-v2/dialogs/add-and-modify-detail-drawing-dialog-v2.tsx index b8650b1a..7577d133 100644 --- a/lib/dolce-v2/dialogs/add-and-modify-detail-drawing-dialog-v2.tsx +++ b/lib/dolce-v2/dialogs/add-and-modify-detail-drawing-dialog-v2.tsx @@ -319,135 +319,8 @@ export function AddAndModifyDetailDrawingDialogV2({ }; const handleCancel = () => { - // 유효성 검사 - if (!registerKind) { - toast.error(t("addDetailDialog.selectRegisterKindError")); - return; - } - - if (drawingUsage !== "CMT") { - if (!revision.trim()) { - toast.error(t("addDetailDialog.selectRevisionError")); - setRevisionError(t("addDetailDialog.revisionRequired")); - return; - } - - // Revision 형식 검증 - const revisionValidationError = validateRevision(revision); - if (revisionValidationError) { - toast.error(revisionValidationError); - setRevisionError(revisionValidationError); - return; - } - } - - // Add 모드일 때만 파일 필수 - if (mode === "add") { - if (!drawing) return; - if (!drawingUsage) { - toast.error(t("addDetailDialog.selectDrawingUsageError")); - return; - } - if (files.length === 0) { - toast.error(t("addDetailDialog.selectFilesError")); - return; - } - } - - // Edit 모드일 때는 detailDrawing 필수 - if (mode === "edit" && !detailDrawing) { - toast.error(t("editDetailDialog.editError")); - return; - } - - try { - setIsSubmitting(true); - - // FormData 구성 - const formData = new FormData(); - formData.append("userId", userId); - formData.append("userNm", userName); - formData.append("vendorCode", vendorCode); - formData.append("email", userEmail); - - if (mode === "add" && drawing) { - const uploadId = uuidv4(); - - const dwgList = [ - { - Mode: "ADD", - Status: "Submitted", - RegisterId: 0, - ProjectNo: drawing.ProjectNo, - Discipline: drawing.Discipline, - DrawingKind: drawing.DrawingKind, - DrawingNo: drawing.DrawingNo, - DrawingName: drawing.DrawingName, - RegisterGroupId: drawing.RegisterGroupId, - RegisterSerialNo: 0, - RegisterKind: registerKind, - DrawingRevNo: drawingUsage === "CMT" ? null : revision, - Category: "TS", - Receiver: null, - Manager: "", - RegisterDesc: comment, - UploadId: uploadId, - RegCompanyCode: vendorCode, - }, - ]; - formData.append("dwgList", JSON.stringify(dwgList)); - - // 파일 추가 - formData.append("fileCount", String(files.length)); - files.forEach((file, index) => { - formData.append(`file_${index}`, file); - }); - - } else if (mode === "edit" && detailDrawing) { - const dwgList = [ - { - Mode: "MOD", - Status: detailDrawing.Status, - RegisterId: detailDrawing.RegisterId, - ProjectNo: detailDrawing.ProjectNo, - Discipline: detailDrawing.Discipline, - DrawingKind: detailDrawing.DrawingKind, - DrawingNo: detailDrawing.DrawingNo, - DrawingName: detailDrawing.DrawingName, - RegisterGroupId: detailDrawing.RegisterGroupId, - RegisterSerialNo: detailDrawing.RegisterSerialNo, - RegisterKind: registerKind, - DrawingRevNo: drawingUsage === "CMT" ? null : revision, - Category: detailDrawing.Category, - Receiver: detailDrawing.Receiver, - Manager: detailDrawing.Manager, - RegisterDesc: comment, - UploadId: detailDrawing.UploadId, - RegCompanyCode: detailDrawing.RegCompanyCode || vendorCode, - }, - ]; - formData.append("dwgList", JSON.stringify(dwgList)); - formData.append("fileCount", "0"); // 수정 시에는 메타데이터만 수정 (파일 수정은 별도) - } - - // Action 호출 - const result = await editDetailDwgReceiptV2(formData); - - if (result.success) { - toast.success(mode === "add" ? t("addDetailDialog.addSuccess") : t("editDetailDialog.editSuccess")); - resetForm(); - onComplete(); - onOpenChange(false); - } else { - throw new Error("Action failed"); - } - - } catch (error) { - console.error("상세도면 처리 실패:", error); - toast.error(mode === "add" ? t("addDetailDialog.addErrorMessage") : t("editDetailDialog.editErrorMessage")); - } finally { - setIsSubmitting(false); - } + resetForm(); + onOpenChange(false); }; // DrawingUsage가 변경되면 RegisterKind 초기화 diff --git a/lib/dolce-v2/sync-service.ts b/lib/dolce-v2/sync-service.ts index ea56b239..7f866955 100644 --- a/lib/dolce-v2/sync-service.ts +++ b/lib/dolce-v2/sync-service.ts @@ -1,6 +1,9 @@ "use server"; import fs from "fs/promises"; +import { createReadStream, createWriteStream } from "fs"; +import { Readable } from "stream"; +import { pipeline } from "stream/promises"; import path from "path"; import { v4 as uuidv4 } from "uuid"; import db from "@/db/db"; @@ -41,11 +44,15 @@ async function ensureUploadDir() { async function saveFileToLocal(file: File): Promise<SavedFile> { await ensureUploadDir(); - const buffer = Buffer.from(await file.arrayBuffer()); const uniqueName = `${uuidv4()}_${file.name}`; const localPath = path.join(LOCAL_UPLOAD_DIR, uniqueName); - await fs.writeFile(localPath, buffer); + // Stream: Web Stream (file.stream()) -> Node Writable Stream (fs.createWriteStream) + // Readable.fromWeb requires Node 18+ + const readable = Readable.fromWeb(file.stream() as any); + const writable = createWriteStream(localPath); + + await pipeline(readable, writable); return { originalName: file.name, @@ -254,16 +261,20 @@ async function uploadLocalFiles(uploadId: string, userId: string, files: SavedFi const file = files[i]; const fileId = uuidv4(); - // 로컬 파일 읽기 - const fileBuffer = await fs.readFile(file.localPath); + // 로컬 파일 읽기 (Stream) + const fileStream = createReadStream(file.localPath); // 업로드 API 호출 const uploadUrl = `${DOLCE_API_URL}/PWPUploadService.ashx?UploadId=${uploadId}&FileId=${fileId}`; const uploadResponse = await fetch(uploadUrl, { method: "POST", - headers: { "Content-Type": "application/octet-stream" }, - body: fileBuffer, - }); + headers: { + "Content-Type": "application/octet-stream", + "Content-Length": file.size.toString() + }, + body: fileStream as any, // Node stream as body + duplex: "half", // Required for Node streams + } as RequestInit & { duplex?: string }); if (!uploadResponse.ok) throw new Error(`File upload failed: ${uploadResponse.status}`); |
