node.js - 如何在 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。非常感谢您的帮助。
解决方案
我使用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);
我希望这也会对某人有所帮助。
推荐阅读
- javascript - 如何使用nodejs mysql从html中的表单传递id
- java - 如何通过 Activator 激活 AEM bundel?
- android - 如何获取可上传的文件路径链接
- c++ - opencv 4.0 无法保存视频
- sql - BigQuery:如何计算过去 2 天不同访问者的运行计数
- java - 垃圾收集(本地参考)
- php - isset($_POST['submit']) 未在按钮单击时触发
- javascript - html 线图显示设备状态所需的建议
- java - TextView textView = (TextView) findViewById(R.id.textView) 是向上转换还是向下转换?
- mysql - 从数据库中的 5 个字符字符串中查找下一个自由值