pdf内容获取失败主因是生成、路径、权限或解析逻辑问题,需逐项排查:检查mpdf生成是否有效、路径是否为绝对系统路径且可读、读取方式是否匹配用途(下载用sendfile,解析用专用库),并规避编码陷阱。

获取PDF文件内容失败,通常不是“读不到”,而是“读得不对”或“根本没走到读取那步”。关键要分清是生成失败、路径失效、权限阻断,还是内容解析逻辑出错。下面按高频场景逐项排查。
检查PDF生成环节是否真正产出有效文件
很多问题其实卡在生成阶段——你以为生成了PDF,实际是空白页、500错误页,或HTML混入PDF流中。确认方式很简单:
- 用
$mpdf->Output('test.pdf', 'F')强制保存到服务器磁盘,然后手动用ls -l和file test.pdf检查文件是否存在、大小是否非零、是否为PDF格式 - 若生成时抛出
MPDFException(如字体缺失、CSS解析失败),默认被静默吞掉;务必在try/catch中捕获并记录完整异常信息 - 中文乱码或样式丢失,大概率是未启用
$mpdf->useAdobeCJK = true或未正确加载中文字体(如simhei.ttf需放在@vendor/mpdf/mpdf/ttfonts/并配置fontdata)
验证文件路径与访问权限是否真实可达
路径写错、权限不足、符号链接断裂,是生产环境最常被忽略的硬伤:
- 不要用
@web拼URL路径去读PDF(如file_get_contents(Yii::getAlias('@web').'/uploads/a.pdf')),MPDF需要的是@webroot下的绝对文件系统路径 - 用
is_file($path) && is_readable($path)双重校验,而不仅是file_exists();尤其注意Web服务器用户(如www-data)是否有权读取该路径 - 若PDF由临时目录(如
@runtime)生成,检查runtime目录是否可写,且PHP进程有执行umask后的真实权限
排查内容读取方式是否匹配用途
“获取内容”目标不同,手段差异很大:
- 若只是想把PDF作为二进制流发送给浏览器下载,直接用
$response->sendFile($filePath, $fileName),它自动处理MIME、断点续传等,无需自己file_get_contents() - 若需解析PDF文本(如提取签名位置、识别水印),不能依赖
file_get_contents()——那是读原始字节,不是解码PDF结构;应使用setasign/fpdi或samesk/pdf-parser等专用库 - 若PDF含动态生成内容(如带变量的模板),确保
render()返回的HTML已完全渲染完毕,没有JS延迟加载或AJAX异步插入的内容残留
留意编码与字符集陷阱
PDF本身是二进制格式,但生成过程中的文本输入极易引发隐性错误:
- 模板视图里避免混用UTF-8 BOM头和
mb_convert_encoding(),BOM会污染PDF头部导致浏览器解析失败 - 从数据库读取字段用于PDF内容时,确认字段字符集是
utf8mb4,且PDO连接已设置charset=utf8mb4,否则中文可能变成 - 使用
attachContent()发邮件附PDF时,若传入的是file_get_contents()结果,必须确保该二进制数据未被trim()或str_replace()意外修改











