2
0
0

博客在线生成工具 · 可行性报告

2026-09-06
2026-09-06

博客在线生成工具 —— 可行性报告

目标:在 suy2blog.cn(Halo 2.26.1)上部署一个入口,客户录入关键信息,系统识别后将信息填入指定 Word 文档,再把多个文档合并成一份 PDF 返回客户。 本文基于对本机(博客 VPS 106.55.246.220)实测的部署事实撰写。


1. 需求拆解

环节 输入 处理 输出
A. 入口 浏览器打开博客页面 Halo 静态页面承载表单 JSON 表单数据
B. 识别 客户关键信息字段 校验/归一化→灌入 word 填好的 docx
C. 落版 模板 word 定向替换 + 保持版式 docx(可 .doc/.wps 输入)
D. 合并 多份 docx 合成单文件 一份 docx
E. 转 PDF 合并后 docx 版式还原 PDF
F. 返回 PDF HTTP 下载/在线预览 客户浏览器

这四个字面上看起来是"浏览器一个页面的事",实际每步都涉及有状态的真实文件格式,所以选型核心在 C/D/E 三环。


1.1 已确定的两前提(形态基线)

本项目两个关键前提经确认后固定为默认基线,报告其余部分在此基础上收敛:

① 模板由你后台预置(形态甲,已采用)

  • 模板(合同/报价等)由你在后台预置入库;客户只填表单字段,无法触碰/上传模板。
  • 好处:范围小、永久保留版式、不需任意上传校验、安全最好、客户体验最好。
  • 形态乙(客户端任意上传 .wps/.doc/.docx):暂不采用;如需开放,另做上传校验/格式兼容,作为独立延展。

② "识别" = 结构化表单字段逐一填(已采用)

  • 模板内字段已由你以 {{占位符}}(或书签)预标;前端把表单字段名对齐,后端按名定向替换,无需 AI / NLP
  • 自然语言一大段话里抽字段:暂不采用;仅在将来接 AI 抽取时再评估,作为可选演进。

基线 = 甲(后台预置模板)+ 结构化字段逐一替换。全文的架构、安全、风险都按此口径收窄。


2. 可行性结论(先给答案)

可行(形态甲 + 结构化字段,见 §1.1)。前提是把"C/D/E 三环"的代码跑在后端——Halo 本身只是纯前端入口。

架构定式(本报告全篇基石):

客户浏览器
   │  HTTPS:填结构化表单字段(姓名/金额/日期…)
   ▼
Halo 博客页面  ←── suy2blog.cn(nginx 反代 halo:8090)
   │  仅承载静态页面 + JS(不跑 word 逻辑;不接收/上传模板)
   ▼
你控制的后端机/VPS(模板由你后台预置在本机)
   ├─ 接收字段 JSON
   ├─ (LibreOffice headless) 兼容 .doc/.wps 占位模板
   ├─ python-docx 按 {{字段}} 定向填充 + 多份合并
   └─ 返回合并后的 PDF

关键结论分三层:

  • 入口层:Halo「页面」本就支持发 HTML/脚本,配 pub.suy2blog.cn 或你选的新二级域即可。Halo 无需改插件、无需跑代码。
  • 填充层:真实 .doc/.wps 模板差异在于格式兼容链,本报告给出 LibreOffice headless 作为统一格式枢纽的稳妥办法。
  • ⚠️ 资源约束:实测博客这台 VPS 仅 2 核 / 2GB 内存,已用 1.4G,且无 soffice/java/node/pip。若执行端也放这台,内存吃紧(LibreOffice 单实例约 300–500MB),需要精简并发换更大执行机。评估已在 §6 量化。

3. 关键识别 — 填进 Word 的技术选型

识别"客户关键信息"本质是模板变量定位 + 定向替换。由于模板由你预置(§1.1 形态甲),实际就是你预先把字段以占位符/书签标好,后端按名填。三种做法按你手头模板的真实格式(可能本就含 .wps/.doc,或你愿整理成 .docx)排序:

3.1 曲线 A — .docx 原生占位符(推荐主路径,你的预置模板整理为 .docx)

  • 你预置模板内写占位符 {{客户名称}} {{金额大写}} {{身份证}},后端一个不漏地替换成 field 数据。
  • python-docx(纯 Python,进 zip 改 document.xml)即可逐段定位替换,不影响其它排版,最轻、部署最简单(pip 一个 wheel 就好)。
  • 适合结构固定的合同/报价/委托书等。正式做成后台模板时,建议把 .wps/.doc 手头件用 Word/WPS「另存为 .docx」归到本曲线,转换最稳、失真最小、无需每次转码。
  • 版式还原靠你预置模板的样式,几乎零失真。

3.2 曲线 B — LibreOffice headless 统一「格式枢纽」(.doc/.wps 也能转)

soffice --headless --convert-to docx "输入.doc" 能把旧式 .doc、甚至部分 .wps 先进 docx;.docx 也可再转 pdf。

  • 生态标配,抗杂格式,能覆盖你"类型都可能"的场景,也是 §5 合并与转 PDF 的同一条链,代码量最少。
  • 唯一注意:LibreOffice 转 wps 依赖它把 .wps 当 OpenDocument 旧格式读,个别细排版(窗体/特殊宏)可能丢,需样品实测。
  • 代价:soffice 要装进执行机,内存偏大。

3.3 曲线 C — 富文本注入(若目标 doc 大量用「书签/表格填空」而非占位符)

某些模板是表格里留空格/书签(如 WPS 表单域)。此时识别不仅是查占位符,还要能定位 书签(TocBookmark) 或第几行第几列表格单元,用 python-docx 遍历 w:bookmarkStart+逐个填。

  • 复杂度线性上升,但更贴近"识别后插入到对应位置"的表述。报告按能支持为准。

前端 offer(备选说明):填字段、合并理论上全在浏览器可做(docx=zip+xml,有 browser-side 库)。但形态甲要后台保留版式一致性与记录,且 .doc/.wps 需浏览器外先转码——故本项目不采用纯前端生成,统一由后端处理,前端只做表单采集。


4. 多份 word 合并成一份

方案 做法 保真 备注
docx 原生拼接(推荐,后端 python-docx) 把多份已填 docx 当作 ZipFile 读,逐段追加 paragraph 进同一 Document,保留每份样式 继承主流样式,失真小 同段合并时页码/页眉按宿主文档;若要各自分页,段落前插 w:pageBreakBefore
LibreOffice 合并 若干 docx 先转 pdf 再 pdf merge 按"每份一屏"融合 用于你不想要 word 结构、只要整本 PDF,最简单
Java docx4j 纯 java 大批量/高保真 最高 执行机需 JVM,2GB 机器偏重

本项目推荐 python-docx 合并(C 端保持 docx),再由同一条 LibreOffice 链转整本 PDF


5. 整体技术栈(推荐落地)

(前端入口 + 后端处理)推荐默认栈:

后端(执行机)                入口(博客侧 - Halo)
  api 服务(FastAPI)   ◄───   Halo 静态页面
  python-docx(填/合并)         (form + JS fetch → 后端)
  LibreOffice headless
  (.doc/.wps→docx;docx→pdf)
角色 选型 理由
语言 Python 3.11+ python-docx 生态最稳、代码最短;执行机现在可能需装 python3-pip
API FastAPI 自带 OpenAPI,前端能自动出客户端
填/合 python-docx 见 §3/§4
转 PDF + 兼容 LibreOffice headless 一条链满足 .doc/.wps 转 docx 与 docx→pdf
进程 systemd unit,监听 127.0.0.1 指定端口,nginx 反代对外 与本机其它服务一致
前端 Halo 单页嵌入 <form>+fetch 到后端 纯静态,无插件依赖

(若执行机无 JVM,避免 Java/docx4j 路线,python-docx 足够。)


6. 执行机资源核算(实测约束)

博客 VPS 现况(本次实测):

  • Debian 13 trixie,2 核 / 1.9GiB,used 1.4G、free 只有 ~100M、available ~515M。
  • 已装 python3.13 但无 pip无 soffice/LibreOffice、无 node、无 java;docker 26 可用
  • 目前仅跑 halo 容器 + nginx。

固 while 执行机能 Docker(已被 docker 可用证实),新增一个处理容器含 FastAPI+soffice,内存需求粗算:

  • LibreOffice headless 转一份 office 文档约 200–450 MB 峰值(视模板/字体)。
  • python API 服务本身 <120 MB。
  • 单并发跑一次约需 350–550 MB

∴ 如果就在这台 2GB 机器上同时顶着 halo+certbot+authelia,只宜设低并发(1–2),页面给用户提示排队;若想要 3+ 并发或模板很大,建议放到更大规格执行机(4G 或你其它机器),博客 VPS 只做反代。

推荐以「执行机 ≥4G」为基线;若坚持用这台 2GB 博客机,按「低并发 1–2」实现(正文 §6 已量化)。


7. 中文字体与单次耗时(客户感知关键)

中文字体是转 PDF 最常见的坑。

  • LibreOffice 容器里若没装中文字体,docx→pdf 会用默认 latin 字体糊掉中文(乱码/方块)。
  • 落地方案:执行机/容器内安装中文字体,例如 apt install fonts-noto-cjk fonts-wqy-microhei,并把模板用到的「宋体/黑体/Times」映射到已装字体(fonts 别名表或 soffice 的 fontconfig 配置)。这几行是上线的必要条件,MVP 就要验证。

单次耗时估算(冷启动最常见):

  • 首次 soffice 启动 profile 较慢,服务应保持一个常驻 soffice(headless --accept 监听或系统进程方式),不要每次生成都起新实例。
  • 单份模板填充 + 转 PDF(几页合同):冷启动可 1–3s,热启动 <1s;多份合并 + 转整本:通常 2–6s。
  • 对在线入口几乎无感;只在并发排队的场景提示「正在生成,请稍候」。

8. 安全与鉴权

形态甲(模板后台预置、客户只提交结构化字段)把攻击面收敛得很窄,威胁面主要是表单滥用 + 后端入口暴露 + 生成文件泄露

  • 后端只允许从 nginx 本机(127.0.0.1)进来,不暴露公网;入参做长度/类型白名单(姓名/金额/日期等按字段限制格式)。
  • 客户不接触模板文件,因此无任意文件上传/路径穿越/宏风险(LibreOffice 无宏更安全)。模板入库是 后台管理操作(非线上接口),存于只读卷。
  • 生成过程跑在独立服务进程/轻量容器,工作目录用临时目录、每请求用完即删,避免残 file 与越权访问常量模板。
  • 模板 id 与 PDF 均需权限/generate?template=<templateId> 应对所用模板类型做权限判断(避免遍历他人成果);返回的 PDF 用一次性临时 URL + 短期失效,视客户场景可加访问口令(复用你的 authelia / 通用口令习惯)。
  • 频控与成本:office 转换偏 CPU/内存,需按 IP 做速率限制,防止被刷形成拒绝服务耗光 §6 的低内存预算。

9. 推荐实施节奏(MVP → 增量)

  1. MVP:固定模板 .docx(含 {{}} 占位符)→ FastAPI 一个端 /generate(accept 字段 json + 模板 id)→ python-docx 填充 → LibreOffice 转 pdf → 返回二进制。博客页一个 <form>(4–8 个字段)。
  2. 扩展:支持多份模板合并生成一份 PDF;.doc/.wps 模板经 LibreOffice 入库管理(这是你的后台操作,非客户功能,用于兼容旧格式手头模板)。
  3. 优化:result 缓存、排队提示、在线预览 PDF、结构化日志、后台模板 CRUD(增删改由你维护)。

10. 结论一句话

在单独的后端服务上(python-docx 处理 + LibreOffice headless 转 PDF),把 Halo 当纯前端入口,完全可以在 suy2blog.cn 上线线上 Word 生成+合并 PDF 工具;主要成本在执行机资源 ≥4G.doc/.wps 需先实测一张模板转换保真,二者均可控可行。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

博客在线生成工具 · 可行性报告
/archives/online-doc-generator-feasibility
作者
苏浚淇
发布于
2026-09-06
许可协议
CC BY-NC-SA 4.0

评论

欢迎来到我的博客!