diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-06 20:11:15 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-06 20:11:15 +0900 |
| commit | d20a3b0f899bc55369c2410ec7244c24391928da (patch) | |
| tree | 80196bdf99b7b3a9d0834f26e0700d7e7c3a066b | |
| parent | 4c07f977c951cd99dd50d3bdaad0437e3dd55e6d (diff) | |
(김준회) 벤더 견적 응답: 첨부파일 다운로드시 암호화 해제해서 다운로드 받도록 변경
| -rw-r--r-- | lib/rfq-last/vendor-response/editor/attachments-upload.tsx | 50 | ||||
| -rw-r--r-- | lib/rfq-last/vendor-response/rfq-attachments-dialog.tsx | 61 |
2 files changed, 90 insertions, 21 deletions
diff --git a/lib/rfq-last/vendor-response/editor/attachments-upload.tsx b/lib/rfq-last/vendor-response/editor/attachments-upload.tsx index 96a88ef7..be9263f5 100644 --- a/lib/rfq-last/vendor-response/editor/attachments-upload.tsx +++ b/lib/rfq-last/vendor-response/editor/attachments-upload.tsx @@ -40,6 +40,7 @@ import { formatBytes } from "@/lib/utils" import { cn } from "@/lib/utils" import { toast } from "sonner" import { deleteVendorResponseAttachment } from "../../service" +import { decryptWithServerAction } from "@/components/drm/drmUtils" interface FileWithType extends File { attachmentType?: "구매" | "설계" @@ -254,6 +255,53 @@ export default function AttachmentsUpload({ setDeleteDialogOpen(false) setFileToDelete(null) } + + // 기존 첨부파일 다운로드 핸들러 (DRM 복호화 적용) + const handleExistingFileDownload = async (file: any) => { + try { + // 1. 파일 가져오기 + const fileUrl = file.filePath.startsWith('http') + ? file.filePath + : `${window.location.origin}${file.filePath}` + + toast.loading(`파일 다운로드 준비 중...`, { id: `download-${file.id}` }) + + const response = await fetch(fileUrl) + if (!response.ok) { + throw new Error(`파일 다운로드 실패: ${response.status}`) + } + + // 2. Blob을 File로 변환 + const blob = await response.blob() + const fileObj = new File([blob], file.originalFileName, { type: blob.type }) + + // 3. DRM 복호화 + toast.loading(`파일 복호화 중...`, { id: `download-${file.id}` }) + const decryptedBuffer = await decryptWithServerAction(fileObj) + + // 4. 복호화된 파일 다운로드 + const decryptedBlob = new Blob([decryptedBuffer], { type: blob.type }) + const downloadUrl = URL.createObjectURL(decryptedBlob) + + const link = document.createElement('a') + link.href = downloadUrl + link.download = file.originalFileName + link.style.display = 'none' + + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + + // 메모리 정리 + setTimeout(() => URL.revokeObjectURL(downloadUrl), 100) + + toast.success(`파일 다운로드 완료: ${file.originalFileName}`, { id: `download-${file.id}` }) + } catch (error) { + console.error("파일 다운로드 오류:", error) + const errorMessage = error instanceof Error ? error.message : "파일 다운로드에 실패했습니다" + toast.error(errorMessage, { id: `download-${file.id}` }) + } + } // 파일 아이콘 가져오기 const getFileIcon = (fileName: string) => { @@ -509,7 +557,7 @@ export default function AttachmentsUpload({ type="button" variant="ghost" size="sm" - onClick={() => window.open(file.filePath, '_blank')} + onClick={() => handleExistingFileDownload(file)} > <Download className="h-4 w-4" /> </Button> diff --git a/lib/rfq-last/vendor-response/rfq-attachments-dialog.tsx b/lib/rfq-last/vendor-response/rfq-attachments-dialog.tsx index 3ca01191..cc7aaba9 100644 --- a/lib/rfq-last/vendor-response/rfq-attachments-dialog.tsx +++ b/lib/rfq-last/vendor-response/rfq-attachments-dialog.tsx @@ -26,6 +26,7 @@ import { toast } from "sonner" import { RfqsLastView } from "@/db/schema" import { getRfqAttachmentsAction } from "../service" import { downloadFile, quickPreview, smartFileAction, formatFileSize, getFileInfo } from "@/lib/file-download" +import { decryptWithServerAction } from "@/components/drm/drmUtils" // 첨부파일 타입 interface RfqAttachment { @@ -132,34 +133,54 @@ export function RfqAttachmentsDialog({ isOpen, onClose, rfqData }: RfqAttachment loadAttachments() }, [isOpen, rfqData.id]) - // 파일 다운로드 핸들러 + // 파일 다운로드 핸들러 (DRM 복호화 적용) const handleDownload = async (attachment: RfqAttachment) => { const attachmentId = attachment.attachmentId setDownloadingFiles(prev => new Set([...prev, attachmentId])) try { - const result = await downloadFile( - attachment.filePath, - attachment.originalFileName, - { - action: 'download', - showToast: true, - showSuccessToast: true, - onSuccess: (fileName, fileSize) => { - console.log(`다운로드 완료: ${fileName} (${formatFileSize(fileSize || 0)})`) - }, - onError: (error) => { - console.error(`다운로드 실패: ${error}`) - } - } - ) - - if (!result.success) { - console.error("다운로드 결과:", result) + // 1. 파일 가져오기 + const fileUrl = attachment.filePath.startsWith('http') + ? attachment.filePath + : `${window.location.origin}${attachment.filePath}` + + toast.loading(`파일 다운로드 준비 중...`, { id: `download-${attachmentId}` }) + + const response = await fetch(fileUrl) + if (!response.ok) { + throw new Error(`파일 다운로드 실패: ${response.status}`) } + + // 2. Blob을 File로 변환 + const blob = await response.blob() + const file = new File([blob], attachment.originalFileName, { type: blob.type }) + + // 3. DRM 복호화 + toast.loading(`파일 복호화 중...`, { id: `download-${attachmentId}` }) + const decryptedBuffer = await decryptWithServerAction(file) + + // 4. 복호화된 파일 다운로드 + const decryptedBlob = new Blob([decryptedBuffer], { type: blob.type }) + const downloadUrl = URL.createObjectURL(decryptedBlob) + + const link = document.createElement('a') + link.href = downloadUrl + link.download = attachment.originalFileName + link.style.display = 'none' + + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + + // 메모리 정리 + setTimeout(() => URL.revokeObjectURL(downloadUrl), 100) + + toast.success(`파일 다운로드 완료: ${attachment.originalFileName}`, { id: `download-${attachmentId}` }) + console.log(`다운로드 완료: ${attachment.originalFileName} (${formatFileSize(decryptedBlob.size)})`) } catch (error) { console.error("파일 다운로드 오류:", error) - toast.error("파일 다운로드에 실패했습니다") + const errorMessage = error instanceof Error ? error.message : "파일 다운로드에 실패했습니다" + toast.error(errorMessage, { id: `download-${attachmentId}` }) } finally { setDownloadingFiles(prev => { const newSet = new Set(prev) |
