队列运行Browsershot生成PDF时无法加载外部图片与样式
解决方案
核心问题分析
队列环境与浏览器请求环境的核心差异在于:队列进程运行时可能未正确加载APP_URL配置,导致asset()生成的资源路径为相对路径或无效域名;同时队列进程的权限、网络访问策略也可能影响资源加载。
1. 修复Supervisor队列命令错误
你的Supervisor配置中command字段存在重复的PHP路径,这会导致队列进程无法正常启动或运行异常:
原错误命令:
command=/RunCloud/Packages/php81rc/bin/php /RunCloud/Packages/php81rc/bin/php /server/path/laravel/artisan queue:work database --queue=default --sleep=3 --tries=3 --timeout=1000000
修正为:
command=/RunCloud/Packages/php81rc/bin/php /server/path/laravel/artisan queue:work database --queue=default --sleep=3 --tries=3 --timeout=1000000
修改后重启Supervisor:
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl restart test_worker:*
2. 确保队列进程使用正确的APP_URL
队列进程可能未加载正确的环境变量,导致asset()生成的资源路径无法被Browsershot访问:
- 在Supervisor配置的
[program:test_worker]块中添加环境变量,指定完整的外部可访问域名:
environment=APP_URL=https://your-domain.com
- 或者在队列任务中强制设置
APP_URL:
config(['app.url' => 'https://your-domain.com']); $content = view('site-report.cover-template', ['site' => $this->site])->render();
- 替换Blade中的
asset()为url(),确保生成绝对路径:
<link rel="stylesheet" href="{{ url('css/pdf.css') }}"> <script src="{{ url('js/app.js') }}"></script>
3. 内联静态资源(彻底解决路径问题)
直接将CSS/JS内容内联到HTML中,避免依赖外部资源加载:
修改Blade布局的head部分:
<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }}</title> <!-- Fonts --> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"> <!-- 内联CSS --> <style>{!! file_get_contents(public_path('css/pdf.css')) !!}</style> <!-- 内联JS(如果不需要可省略,或按需内联) --> <script>{!! file_get_contents(public_path('js/app.js')) !!}</script> </head>
4. 调整Browsershot的资源加载策略
优化等待配置,确保资源完全加载:
$content = view('site-report.cover-template', ['site' => $this->site])->render(); Browsershot::html($content) ->noSandbox() ->ignoreHttpsErrors() ->setNodeBinary('/usr/bin/node') ->setNpmBinary('/usr/bin/npm') ->margins(0, 2, 0, 2) ->format('A4') ->setOption('args', ['--disable-web-security', '--no-sandbox']) ->showBackground() ->waitUntilNetworkIdle(5000) // 延长网络空闲等待时间至5秒 ->save($targetFullPath);
注:移除了重复的noSandbox()和waitUntilNetworkIdle()调用,合并参数配置
5. 检查队列进程的文件权限
确保runcloud用户拥有读取public目录资源的权限:
chown -R runcloud:runcloud /server/path/laravel/public chmod -R 755 /server/path/laravel/public chmod 644 /server/path/laravel/public/css/pdf.css /server/path/laravel/public/js/app.js
内容的提问来源于stack exchange,提问作者thursday_dan
相关产品推荐
相关产品推荐

