首页 > 解决方案 > 如何在 NodeJS 中使用带有图表和谷歌地图的 html 生成 PDF

问题描述

我想在 Nodejs 中将 HTML 导出为 PDF。我的 HTML 文件包含图表、图形、图像和表格数据。我已经创建了带有把手解析的 HTML,并为 pdf 的 HTML 创建了一个公共 URL。我尝试使用HTML-PDF NPM 包将 HTML 导出为 pdf,但它无法加载图表、地图等,只能加载带有表格数据的简单 HTML。这是我尝试使用 HTML 页面链接导出的示例:

const requestify = require('requestify');
const path = require("path");
const pdf = require('html-pdf');
const externalURL = `myurl.com/pdf-html`;
requestify.get(externalURL).then(function(response) {
    // Get the raw HTML response body
    const html = response.body;
    const config = { format: 'A4',"base": `file:///${path.resolve("./public")}`};
    // Create the PDF
    pdf.create(html, config).toFile('./public/generated.pdf', function(err, response) {
        if (err) {
            console.log("error");
            return console.log(err);
        }
        res.attachment('report.pdf');
        return res.status(200).send(response);
      });
 });

这是我试图以 PDF 格式导出的 HTML 文件。

<html>

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <style>
        #map-canvas {
            width: 500px;
            height: 350px;
        }
    </style>
</head>

<body>
    <h1>HTML to PDF</h1>
    <div id="chart"></div>
    <div id="map-canvas"></div>
    <table>
        <thead>
            <th>Site</th>
            <th>Site Name</th>
            <th>Location</th>
            <th>Status</th>
        </thead>
        <tbody>
            {{#if records}}
                {{#each records}}
                    <tr>
                        <td><img src="{{this.site}}" style="width: 25px;height: 35px;"></img></td>
                        <td>{{this.siteName}}</td>
                        <td>{{this.location}}</td>
                        <td>{{this.status}}</td>
                    </tr>
                {{/each}}
            {{/if}}
        </tbody>
    </table>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>        

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places,geometry"></script>

    <script>
        $(document).ready(function() {
            var options = {
                chart: { type: 'line' },
                series: [{
                    name: 'sales',
                    data: [30, 40, 35, 50, 49, 60, 70, 91, 125]
                }],
                xaxis: {
                    categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]
                }
            }
            var chart = new ApexCharts(document.querySelector("#chart"), options);
            chart.render();

            function initialize() {
                var myLatLng = new google.maps.LatLng(45.4375, 12.3358),
                    myOptions = {
                        zoom: 5,
                        center: myLatLng,
                        mapTypeId: google.maps.MapTypeId.ROADMAP
                    },
                    map = new google.maps.Map(document.getElementById('map-canvas'), myOptions),
                    marker = new google.maps.Marker({
                        position: myLatLng,
                        map: map
                    });

                marker.setMap(map);
                moveMarker(map, marker);
            }

            function moveMarker(map, marker) {
                //delayed so you can see it move
                setTimeout(function() {
                    marker.setPosition(new google.maps.LatLng(45.4375, 12.3358));
                    map.panTo(new google.maps.LatLng(45.4375, 12.3358));
                }, 1500);
            };

            initialize();
        });
    </script>
</body>

</html>

另外,我收到以下错误:

message=html-pdf: Received the exit code '1'
html-pdf: Evaluation - ReferenceError: Can't find variable: ApexCharts
Stack: at file:////path/to/project/public
, stack=Error: html-pdf: Received the exit code '1'
html-pdf: Evaluation - ReferenceError: Can't find variable: ApexCharts
Stack: at file:////path/to/project/public

at ChildProcess.respond (path/to/project/node_modules/html-pdf/lib/pdf.js:121:31)
at ChildProcess.emit (events.js:315:20)
at Process.ChildProcess._handle.onexit (internal/child_process.js:277:12)
enter code here

我也尝试过使用 puppeteer NPM 包,但这个包的同样问题也无法加载图表和地图。无法在 PDF 中获得完全加载的 HTML。

因此,任何人都知道如何导出包含地图、图表、图像、表格等的 HTML。非常感谢您的帮助。

标签: node.jsexpressexport-to-pdfnode-html-pdf

解决方案


我使用Puppeteer做到了。我在 NodeJS 中创建了一条路由,它可以在我的 PDF 中呈现我想要的 HTML。该路线无需登录即可访问,因此不需要登录。在我的 HTML 文件中,我添加了动态图表、谷歌地图、图像和表格列表。

我通过在导出 PDF 路径中编写以下内容来创建 PDF:

const path = require("path");
const puppeteer = require('puppeteer');

// launch a new chrome instance
const browser = await puppeteer.launch({
     headless: true
});

// create a new page
const page = await browser.newPage()

// Go to URL of HTML that I want to export in PDF
await page.goto(`domain.com/my-pdf-html`, {
       waitUntil: "networkidle0"
});

// Create pdf file of opened page
const pdf = await page.pdf({
    printBackground: true,
    format: 'A4',
    path: `${path.resolve("./public/my-report.pdf")}`
});

// close the browser    
await browser.close();

// Return generated pdf in response
res.contentType("application/pdf");
return res.status(200).send(pdf);

我希望这也会对某人有所帮助。


推荐阅读