From c2f6383d5b63c04d6afdbc81146c18b12b2cdca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B3=E4=BD=A9=E5=BA=AD?= Date: Mon, 14 Jul 2025 13:16:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8F=9B=E8=A1=8C=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/app.cpython-312.pyc | Bin 0 -> 2833 bytes app.py | 36 +++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 __pycache__/app.cpython-312.pyc diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d96f7ea11553aeff6e5dd3ad231f3d8363b89442 GIT binary patch literal 2833 zcmai0O>7&-6`uX!a`{hDlu7+GPGdU`9a(B^qi_ntsBBk}14oE!r7qaCi?wDYF1_4k zW>?XVDU?E0NCpg8N)KY;7~oNbeelu8+=NyrN&F)s>iE?QDa&dWZQ ztUyW0D?XO3U`frZJ`Px+QaB&>v0_C^(R|d$K`T~@=i@$BtwbrAPx?4yb>+LjcF0QQ zQz9~i2W>a<-7rfP-{J0cMjXbGhtUUOiy|PSyZCO0%Mp%&zKp{U;}2jztN~6ukXl$k zz>OCNTeE{b(4#nsySRO>%{1OeIJJy$x1n%5`3$W7Y-7_agP0Mg$8oHpn#)l3zESM;h zy8W5X$l}NuHlLUnb!?^;F5{_^;SqC^aU(7ud-}SGy}~$ET;JjZFjQmCbUn?vxey#~ zQGpo3CNU;Ghs?u7w)K($hOaZj3q9kG=UmfmcjDs74-IV2l!iQSYVzQ|+XsvGvq0TI z2FeQ<<;9PYA;C2W=YTpd<|G=KFy_4WHfeAYtQ)pBo(oV_)7YAtM#Gv`a`24Ba8%Pi zozbl}M}iH}gr@1X?Xb-_wySA>M*GZ>f2V)`(@)CtUcs?7IE7F2a(SpcPg210I|ke! zbbmm*vE=d<(#JUqvEgaMHi+&SCqa|SSod@qB(1xcYzG=hBgFLCPWQ9WZy>K7S_l;n zN-;@j{Ic&sD%}?sMNe+gL7FEUC%{+?9hkHs7AqnT#6`)AaEW4+qs~~7yf~jdlwN7c z6}i~O>75bFIKX8D1Tx(n9!FTgK`yfxs09AMosI`s?FBP9v;YNXQK_I}np^FR#Y_it z#Lw&!`pqI}20doRZRXZ zq5rZAap4MgGO*vn++t@0FMJ)o0-Rm2qGHqsz6!_|Wb~SScFM1NEZoWeFUuX9cYY_c zJNaQ}U5+Y&juc27;q=bPPtd>BV;wq29X^hD$2qkkd|#>k-ohH?9`F&zD&jqKUt9oV zrf?1A;^PbQ5M&ZzVam!)S)VpsbHN}_@N-D!ck; z24SH~)f-TheK!@tN^Ln8A_Kr6EEK6a1-08RqdxK-6((EOHRnc=#!LE~#(dCbS%s!D z!&ER`RtetZjj#x(QC^`~Z6oJ_)B~TZLjkIy=cz**C)Q8=ad7R8n)f7ev^w@Q(RFwB z_Uzrt?MiK|UT7qSt7FgA_}$p;*jnLXYFizwj_k^TmCH+)R|_?9Tke0BNZ!45`&R8# z&21!(RL6GZ=#HG;lGAIys*!E^t>-p2qlety- zX}q^~w61Qx)rg;b6#r}d{L`MkFHYCId+*it&D7UDgKNUmZt$*tp?6;6i`+^So&afZd=Z>Jpx|7!ocX#=<--oL7~hSQtkbn zfx)eT!JUEATLY&bU2F`TZDikjT=;VC%i@!BSGTfPo01q+nn(;N{!5YTqroY7ruDK( zSVj|8%xQO&K7O|7x?i`-Ud0sey*ql4<%Jg`b~J( ziAw_|X9f}`N+4le&mb&){Pz=5&4D0ip+{IzZoQv=aH{88@AY|d1sLp2bnipglmtQe z1|8i)@9v>D_Rx_%^!6Sa+(Yl|p)=p0#NU)H$y?J)K=gi}?)zCJ&^bBRH;T@FOLYY4)wYev`pEa^0+vvheSrEF`axW1KaJgb& kCA*Ye9c~DHO|f54)^0Ts44c>g#fE(eiT(d%bl?5|01rfu@Bjb+ literal 0 HcmV?d00001 diff --git a/app.py b/app.py index 897bf46..4313921 100644 --- a/app.py +++ b/app.py @@ -2,8 +2,10 @@ from fastapi import FastAPI, Request from fastapi.staticfiles import StaticFiles from pydantic import BaseModel from reportlab.pdfgen import canvas -from reportlab.pdfbase import pdfmetrics +from reportlab.lib.pagesizes import A4 from reportlab.pdfbase.ttfonts import TTFont +from reportlab.pdfbase import pdfmetrics +from reportlab.pdfbase.pdfmetrics import stringWidth import uuid, os app = FastAPI() @@ -11,13 +13,7 @@ app = FastAPI() os.makedirs("static", exist_ok=True) app.mount("/static", StaticFiles(directory="static"), name="static") -# ✅ 註冊中文字體(請確保字體檔案存在) -font_path = "NotoSansTC-Medium.ttf" # 或使用微軟系統內建:msjh.ttc(微軟正黑體) -if os.path.exists(font_path): - pdfmetrics.registerFont(TTFont("MyFont", font_path)) - font_name = "MyFont" -else: - font_name = "Helvetica" # fallback +pdfmetrics.registerFont(TTFont("TWFont", "NotoSansTC-Medium.ttf")) class TextRequest(BaseModel): content: str @@ -27,11 +23,27 @@ def generate_pdf(data: TextRequest, request: Request): filename = f"{uuid.uuid4()}.pdf" filepath = os.path.join("static", filename) - c = canvas.Canvas(filepath) - c.setFont(font_name, 12) - c.drawString(100, 750, data.content[:1000]) + c = canvas.Canvas(filepath, pagesize=A4) + c.setFont("TWFont", 12) + + text_obj = c.beginText(50, 800) + text_obj.setFont("TWFont", 12) + + max_line_width = A4[0] - 50 * 2 # 頁寬扣左右邊距 + + for line in data.content.splitlines(): + while stringWidth(line, "TWFont", 12) > max_line_width: + for i in range(len(line), 0, -1): + if stringWidth(line[:i], "TWFont", 12) <= max_line_width: + text_obj.textLine(line[:i]) + line = line[i:] + break + text_obj.textLine(line) + + c.drawText(text_obj) + c.showPage() c.save() return { - "url": str(request.base_url) + f"static/{filename}" + "download_url": str(request.base_url.rstrip("/")) + f"/static/{filename}" }