Webman本身不内置PDF生成功能,需集成mPDF等外部库;安装composer require mpdf/mpdf,配置UTF-8模式与中文字体路径,用WriteHTML渲染HTML并手动设置Content-Type和Content-Disposition响应头。

Webman 本身不内置 PDF 生成功能,它只是一个高性能 PHP Web 框架(基于 Workerman),导出 PDF 必须依赖外部库或系统工具。直接在 Webman 控制器里调用 mpdf、TCPDF 或 wkhtmltopdf 才是可行路径——别指望框架自动帮你“生成合同 PDF”。
Webman 中怎么集成 mPDF 生成带中文的合同 PDF
mPDF 是 Webman 场景下最平衡的选择:纯 PHP、支持 UTF-8、CSS 兼容性好、模板可复用,且比 DOMPDF 更稳(后者容易因内存超限或字体未注册导致空白页)。
- 安装必须走 Composer:
composer require mpdf/mpdf,不要手动丢文件 - 中文字体不能只放 .ttf 文件,得显式注册:
$mpdf = new \Mpdf\Mpdf(['mode' => 'utf-8', 'format' => 'A4', 'fontDir' => [<strong>DIR</strong>.'/fonts/'], 'fontdata' => ['simhei' => ['R' => 'simhei.ttf']]);
然后在 HTML 中用<span style="font-family: simhei">甲方:张三</span> -
WriteHTML()前务必确保 HTML 字符串已完整渲染(比如用 Twig 预编译),别传含 PHP 语法的原始模板字符串 - 若合同含签名图或公司 Logo,用绝对路径加载(
file://协议不被支持),建议把图片 base64 内联或复制到public/pdf-assets/后拼相对 URL
Webman 调用 wkhtmltopdf 生成高保真发票 PDF 的坑
wkhtmltopdf 渲染效果最接近浏览器,但 Webman 环境下极易翻车:
- 它不是 PHP 库,而是系统级二进制程序,必须确认:
-
shell_exec('which wkhtmltopdf')能返回路径 - PHP 的
disable_functions没禁用exec、shell_exec - Webman 工作进程用户(如 www-data)有执行权限,且能访问网络(若 PDF 页面含
https://外链资源)
-
- URL 必须服务端可访问:不能写
<a href="https://www.php.cn/link/d67c657294b9abc8222519ab83bddda1">https://www.php.cn/link/d67c657294b9abc8222519ab83bddda1</a>,要换成<a href="https://www.php.cn/link/1d40146c766379675bb19be6c641a5f9">https://www.php.cn/link/1d40146c766379675bb19be6c641a5f9</a>,或加--allow ./+ 本地 HTML 文件路径 - 中文乱码主因是没指定系统字体路径,启动时加参数:
--font-dir /usr/share/fonts/truetype/wqy/ --outline-depth 3 - 别用
exec()直接拼接用户输入,URL 和输出路径必须过escapeshellarg()
Webman 输出 PDF 时 HTTP 头和文件名的细节
Webman 的响应对象(Webman\Http\Response)不自动处理 PDF Content-Type,必须手动设:
立即学习“PHP免费学习笔记(深入)”;
- 正确方式:
return response($pdfContent)->withHeader('Content-Type', 'application/pdf')->withHeader('Content-Disposition', 'inline; filename="contract_'.date('YmdHis').'.pdf"'); -
inline表示浏览器内嵌打开,attachment强制下载;别漏filename,否则 Chrome 可能默认存成download.pdf - 文件名含中文?必须 UTF-8 编码后做 RFC 5987 格式转义,例如:
filename*=UTF-8''%E5%90%88%E5%90%8C.pdf,否则 Safari 下显示为乱码 - 大合同(>5MB)别直接 return 响应体,先写入临时文件,再用
readfile()+flush()流式输出,避免内存溢出
真正难的不是“怎么生成”,而是“怎么让每份合同 PDF 在法务审核、财务归档、客户查收时都不出错”:编号唯一性、水印动态生成、哈希落库、字体嵌入验证——这些都得在 Webman 的业务逻辑层兜底,PDF 库只负责“画出来”。



















