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

Laravel中用DOMPdf渲染Chart图表至PDF失败求助

解决Laravel中Chart.js图表无法渲染到DOMPDF生成的PDF问题

核心问题分析

你的代码存在三个关键问题:

  • 前端POST请求未携带CSRF令牌,被Laravel拦截
  • 图片存储路径与PDF视图中引用路径不匹配,DOMPDF无法找到图片
  • 后端重复执行数据库查询(前端已传图片数据,无需再查)

修复步骤与代码修改

1. 修复前端CSRF令牌问题(chart.blade.php)

Laravel默认会验证POST请求的CSRF令牌,需在请求头中加入:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 添加CSRF令牌meta标签 -->
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8">
                <canvas id="myChart" height="100px"></canvas>
            </div>
            <button id="convertButton">pdf</button>
        </div>
    </div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js" charset="utf-8"></script>    

    <script type="text/javascript">
        var labels =  {{ Js::from($labels) }};
        var users =  {{ Js::from($data) }};
      
        const data = {
            labels: labels,
            datasets: [{
                label: 'My First dataset',
                backgroundColor: 'rgb(255, 99, 132)',
                borderColor: 'rgb(255, 99, 132)',
                data: users,
            }]
        };
      
        const config = {
            type: 'line',
            data: data,
            options: {}
        };
      
        const myChart = new Chart(
            document.getElementById('myChart'),
            config
        );
    </script>
    <script>
        const canvas = document.getElementById('myChart');
        const convertButton = document.getElementById('convertButton');
        convertButton.addEventListener('click', () => {
            const canvasData = canvas.toDataURL();
            // 获取CSRF令牌
            const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
            
            fetch('/pdf', {
                method: 'POST',
                headers: { 
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'X-CSRF-TOKEN': csrfToken // 加入CSRF令牌头
                },
                body: `imageData=${encodeURIComponent(canvasData)}`
            })
            .then(response => response.blob()) // 改为获取blob,适配PDF流返回
            .then(blob => {
                // 直接在浏览器中打开PDF
                const url = window.URL.createObjectURL(blob);
                window.open(url);
            });
        });
    </script>
</body>
</html>

2. 修复后端存储与路径问题(/pdf路由处理函数)

去掉多余的数据库查询,修正图片存储路径与访问URL:

public function generatePDF(Request $request)
{
    $imageData = $request->input('imageData');
    if (!$imageData) {
        return response()->json(['message' => '图片数据缺失'], 400);
    }

    // 移除数据URL前缀
    $imageData = str_replace('data:image/png;base64,', '', $imageData);
    $decodedImageData = base64_decode($imageData);

    // 生成唯一文件名(避免覆盖)
    $filename = 'chart_' . uniqid() . '.png';
    
    // 存储到public磁盘(需先执行php artisan storage:link创建符号链接)
    Storage::disk('public')->put($filename, $decodedImageData);
    
    // 获取可访问的图片URL
    $imageUrl = Storage::url($filename);

    // 加载PDF视图
    $pdf = PDF::loadView('pdf', compact('imageUrl'));

    return $pdf->stream('chart.pdf');
}

3. 修复PDF视图图片引用(pdf.blade.php)

使用正确的存储URL而非本地文件路径:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8">                
                <img src="{{ $imageUrl }}" alt="charts" style="width: 100%;">
            </div>
        </div>
    </div>
</body>
</html>

关键注意事项

  1. 执行php artisan storage:link命令,将storage/app/public目录链接到public/storage,确保DOMPDF能访问到存储的图片。
  2. 若DOMPDF仍无法加载图片,可尝试使用绝对URL(如url($imageUrl)),或在DOMPDF配置中开启isRemoteEnabled选项。
  3. 前端返回处理改为blob,直接打开PDF,避免之前的JSON解析错误(因为后端返回的是PDF流,不是JSON)。

内容的提问来源于stack exchange,提问作者Nevil Aghera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:12:13