服务器迁移后wkhtmltopdf结合Snappy生成PDF失败求助
排查wkhtmltopdf+Snappy生成PDF异常的步骤
1. 先验证wkhtmltopdf命令行可用性
直接在服务器终端执行以下命令,排除PHP层问题:
# 生成测试PDF /usr/bin/wkhtmltopdf http://www.github.com test.pdf # 检查文件类型和内容 file test.pdf
如果命令行生成的PDF也异常(比如空白、不是PDF格式),说明是wkhtmltopdf本身的环境问题,优先解决:
- 用
ldd /usr/bin/wkhtmltopdf检查依赖库是否缺失,缺失的话安装对应包(CentOS:yum install libXrender libXext libfontconfig libjpeg-turbo) - 检查服务器网络是否能访问目标URL:
curl http://www.github.com,确认DNS解析和出站请求正常
2. 验证PHP-FPM用户的执行权限
PHP-FPM的运行用户(通常是www-data或apache)可能没有执行wkhtmltopdf的权限,或者无法访问依赖资源:
# 切换到PHP用户执行wkhtmltopdf,输出到标准输出 sudo -u www-data /usr/bin/wkhtmltopdf http://www.github.com -
如果执行失败或输出异常,需要:
- 确保
/usr/bin/wkhtmltopdf对PHP用户有执行权限:chmod +x /usr/bin/wkhtmltopdf - 检查临时目录权限:wkhtmltopdf默认使用系统临时目录(如
/tmp),确保PHP用户有读写权限
3. 修复代码中的错误处理和输出问题
现有代码错误捕获不足,且可能存在输出污染,修改代码如下:
error_reporting(E_ALL); ini_set('display_errors', 1); require $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php'; use Knp\Snappy\Pdf; use Knp\Snappy\Exception\SnappyException; try { $snappy = new Pdf('/usr/bin/wkhtmltopdf'); // 启用调试参数,捕获wkhtmltopdf内部日志 $snappy->setOption('verbose', true); $snappy->setOption('debug-javascript', true); $output = $snappy->getOutput('http://www.github.com'); // 先验证输出是否为有效PDF if (empty($output)) { die('Snappy返回空输出'); } if (substr($output, 0, 4) !== '%PDF') { die('输出不是PDF格式,前100字符内容: ' . substr($output, 0, 100)); } // 清空输出缓冲区,避免之前的输出污染PDF内容 ob_clean(); flush(); header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="file.pdf"'); header('Content-Length: ' . strlen($output)); // 确保浏览器正确接收完整内容 echo $output; } catch (SnappyException $e) { die('Snapy执行错误: ' . $e->getMessage()); } catch (Exception $e) { die('通用错误: ' . $e->getMessage()); }
关键修改点:
- 启用全量错误报告
error_reporting(E_ALL) - 添加异常捕获,捕获Snapy的执行异常
- 验证输出是否为有效PDF(以
%PDF开头) - 清空输出缓冲区,避免之前的空白字符/BOM污染PDF
- 添加
Content-Length头,确保输出完整
4. 检查版本兼容性
对比新旧服务器上的wkhtmltopdf版本:
/usr/bin/wkhtmltopdf --version
如果版本差异较大,可能存在兼容性问题,建议安装和旧服务器一致的版本。
5. 检查PHP环境配置
- 确保
proc_open函数未被禁用(Snapy依赖该函数执行外部命令),查看php.ini中的disable_functions配置 - 检查
open_basedir是否限制了PHP访问/usr/bin/wkhtmltopdf路径,如果有需要添加该路径到open_basedir
内容的提问来源于stack exchange,提问作者Rosamunda
相关产品推荐
相关产品推荐

