feat(535-2): B09 도면 PDF PyMuPDF(AGPL) 제거 — 장마다 SVG 쪽 → 공용 PDF 엔진(Chromium) · pypdf 합치기
- 점선 = 미리 자른 실선 조각(Chromium 이 점선을 채운 윤곽으로 풀어 PDF 3 배 커지는 것 막음) - 글 안 빈칸 그대로(white-space: pre) · 세운 글 방향 = 화면(openwebcad canvas)과 같게 - 못 넣은 그림 = data: 아님 · base64 깨짐 - test_302_2: PDF 읽기 pymupdf → pypdf · add_drawing_page(pymupdf 문서) 시험 → drawing_page(SVG) 로 고침 · 점선 조각 · 빈칸 시험 더함 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
로그인 · 회사 · 프로젝트 권한은 이 라우터가 스스로 검(B09 라우터가 include 하든 앱이 바로 붙이든).
|
||||
저장 안 함 — 매번 만듦 · B07 정본 · 확정 상태 그대로.
|
||||
PDF = 장마다 SVG 쪽 → 공용 PDF 엔진(Chromium · 브라우저 한 번) → pypdf 로 한 벌.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -17,14 +18,14 @@ import json
|
||||
import logging
|
||||
from uuid import UUID
|
||||
|
||||
import pymupdf
|
||||
from fastapi import APIRouter, Depends, Response
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
|
||||
from B09_Estimation.draft import B09_Draft_Print_Drawings_Source as source
|
||||
from B09_Estimation.draft.B09_Draft_Print_Drawings_Pdf import add_drawing_page
|
||||
from B09_Estimation.draft.B09_Draft_Print_Drawings_Pdf import drawing_page
|
||||
from common_util.common_util_auth import require_company, require_project_access, verify_session
|
||||
from common_util.common_util_print_pdf import PrintError, merge_pdfs, render_htmls_to_pdfs
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(
|
||||
@@ -56,15 +57,20 @@ async def get_print_drawings(project_id: UUID) -> JSONResponse:
|
||||
return JSONResponse(items)
|
||||
|
||||
|
||||
#: PDF 만들기 시간 한도 — 기본 + 장마다(큰 도면 묶음)
|
||||
TIMEOUT_BASE_S, TIMEOUT_PER_SHEET_S = 60, 10
|
||||
|
||||
|
||||
def _pdf(drawings: list[dict], ids: list[str]) -> tuple[bytes, dict[str, int]]:
|
||||
doc = pymupdf.open()
|
||||
jobs: list[dict] = []
|
||||
skipped: dict[str, int] = {}
|
||||
for drawing_id, drawing in zip(ids, drawings, strict=True):
|
||||
_, missing = add_drawing_page(doc, drawing)
|
||||
page, size, _, missing = drawing_page(drawing)
|
||||
jobs.append({"html": page, "page_size": size})
|
||||
if missing:
|
||||
skipped[drawing_id] = missing
|
||||
doc.subset_fonts() # 한글 글꼴 = 쓴 글자만
|
||||
return doc.tobytes(garbage=3, deflate=True), skipped
|
||||
timeout = TIMEOUT_BASE_S + TIMEOUT_PER_SHEET_S * len(jobs)
|
||||
return merge_pdfs(render_htmls_to_pdfs(jobs, timeout)), skipped
|
||||
|
||||
|
||||
@router.post("/{project_id}/print/drawings-pdf")
|
||||
@@ -85,6 +91,8 @@ async def post_print_drawings_pdf(
|
||||
body, skipped = await asyncio.to_thread(_pdf, drawings, ids)
|
||||
except ValueError as exc:
|
||||
return _error(400, str(exc))
|
||||
except PrintError as exc:
|
||||
return _error(503, str(exc))
|
||||
except Exception:
|
||||
logger.exception("인쇄 도면 PDF 실패: %s", project_id)
|
||||
return _error(500, "도면 PDF 를 만들지 못했습니다.")
|
||||
|
||||
Reference in New Issue
Block a user