You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

队列运行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:09:23