Paozhu 1.14.0:把 HTML、SVG 与图片直接交给 C++ 生成 PDF

2026-07-21 33 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

Paozhu 1.14.0 把 PDF 生成推进到 C++ Web 应用内部:新增子项目 webpdf,面向 HTML、SVG 和图片生成 PDF,同时继续利用框架原生的图像处理与二维码能力。版本标题还宣布了 XLSX 文件读写,这意味着报表导出、电子凭证和批量文档生成可以更集中地留在 C++ 服务中完成。

webpdf 解决的是服务端文档链路

传统 C++ Web 项目生成 PDF,常见做法是调用浏览器、外部命令行程序,或者把任务转发给另一门语言实现的服务。这些方案能工作,但会增加进程管理、部署镜像和故障排查的复杂度。

根据发布摘要,Paozhu 的 webpdf 子项目用于将 HTML、SVG 和图片生成 PDF,设计灵感来自 FPDF。它更适合生成结构明确的服务端文档,例如:

  • 订单、发票和付款凭证;
  • 带二维码的票据、标签与证书;
  • 后台统计报表和批量归档文件;
  • 由模板与业务数据拼装的下载文档。

发布说明强调其生成速度很快,并将它描述为开源 C++ 生态中非常少见的能力。不过摘要没有给出测试环境、文档规模和对比基线,因此在生产选型前仍应使用自己的模板、字体和图片做基准测试。

原生图片与二维码能力减少外围依赖

Paozhu 已有自己的原生图像处理类,目前支持 JPG 和 PNG,并把二维码生成模块作为内置能力。对常规 Web 文档来说,这几项能力覆盖了最常见的素材:Logo、商品图片、签章、统计图快照和用于核验的二维码。

更重要的是,图片处理、二维码生成和 PDF 输出位于同一套 C++ 技术栈中。服务不必为了生成一张二维码再调用独立工具,也不必专门维护图片转换脚本。不过,当前摘要只明确提到 JPG 和 PNG;如果业务依赖 WebP、TIFF、复杂透明度或专业印刷色彩空间,需要先验证兼容性。

SVG 同样值得关注。图表、矢量 Logo 和条码可以保持清晰,但复杂 CSS、浏览器脚本和现代排版特性是否可用,不能仅凭“支持 HTML”推断。webpdf 更可能适合受控模板,而不是完整复现任意网页。

可以这样准备一个最小文档模板

下面是一个可直接保存为 invoice.html 的输入模板。它只使用基础 HTML、内联 CSS、SVG 和 PNG,便于验证转换器的基础能力。请把 qrcode.png 替换为 Paozhu 内置二维码模块生成的文件,再按照项目实际文档提供的 webpdf API 或命令加载该页面。

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>付款凭证</title>
  <style>
    @page { size: A4; margin: 18mm; }
    body { font-family: sans-serif; color: #202124; }
    header { display: flex; justify-content: space-between; }
    table { width: 100%; border-collapse: collapse; margin-top: 24px; }
    th, td { border-bottom: 1px solid #ddd; padding: 10px 6px; text-align: left; }
    .amount { font-size: 24px; font-weight: 700; }
    .qr { width: 96px; height: 96px; }
  </style>
</head>
<body>
  <header>
    <div>
      <h1>付款凭证</h1>
      <p>单号:PAY-2025-0018</p>
    </div>
    <img class="qr" src="qrcode.png" alt="核验二维码">
  </header>

  <svg width="100%" height="8" viewBox="0 0 600 8"
       xmlns="http://www.w3.org/2000/svg">
    <rect width="600" height="8" fill="#1769aa" />
  </svg>

  <table>
    <thead><tr><th>项目</th><th>数量</th><th>金额</th></tr></thead>
    <tbody><tr><td>年度服务费</td><td>1</td><td>¥1,299.00</td></tr></tbody>
  </table>

  <p class="amount">合计:¥1,299.00</p>
  <p>请扫描二维码核验凭证状态。</p>
</body>
</html>

接入 HTTP 下载接口时,可以采用“渲染、写响应、清理缓冲区”的边界。由于摘要没有给出 1.14.0 的具体类名,下面是明确标注的伪接口,不能直接视为 Paozhu 官方 API;将 WebPdfDocument 和路由类型替换成项目文档中的真实类型即可:

// 假设接口:展示推荐的服务端调用边界,并非 Paozhu 1.14.0 官方签名。
server.get("/receipts/:id.pdf", [](const Request& req, Response& res) {
    const auto html = render_receipt_html(req.param("id"));

    WebPdfDocument pdf;
    pdf.set_base_path("/srv/app/assets");
    const std::string bytes = pdf.render_html(html);

    res.set_header("Content-Type", "application/pdf");
    res.set_header("Content-Disposition", "attachment; filename=receipt.pdf");
    res.write(bytes);
});

这里的 base_path 很关键:HTML 中的相对图片路径必须在服务端映射到受控目录。不要允许请求参数直接拼接本地文件路径,否则 PDF 导出接口可能演变为任意文件读取入口。

XLSX 读写应与 PDF 导出分层

版本标题明确提到了 XLSX 文件读写,但摘要没有提供工作表、单元格类型、公式或样式 API 的细节,因此不宜猜测具体调用方式。工程上可以把 XLSX 与 PDF 看成同一份报表数据的两个输出适配器:PDF 面向阅读和归档,XLSX 面向筛选、计算与二次编辑。

建议先定义与格式无关的数据模型,再分别交给 webpdf 和 XLSX 模块。这样可以避免在 HTML 模板里重新查询数据库,也能保证两个导出版本的金额、日期和行数一致。接入前应重点验证中文字符、日期序列化、大整数精度、公式处理、合并单元格以及大文件内存占用。

上线前检查这些边界

评估 Paozhu 1.14.0 时,不要只测试一页纯文本。至少准备包含中文字体、JPG、透明 PNG、SVG、二维码、分页表格和异常长字段的模板,并记录耗时、峰值内存与输出大小。

还要限制 HTML 长度、图片尺寸、生成时间和并发任务数。若模板或数据来自用户输入,应过滤远程资源、脚本和本地路径;对生成结果设置正确的 Content-Type 与下载文件名。对于 XLSX,则应防范以 =, +, -@ 开头的用户文本触发表格公式注入。

Paozhu 1.14.0 的实际价值,不只是多了两个文件格式,而是让 C++ Web 服务可以缩短文档生成链路。是否适合生产环境,最终取决于模板兼容度、字体处理、资源隔离以及在真实报表规模下的性能数据。


相关推荐