是否可以使用 PhantomJS 和 Node 从模板动态生成 PDF?
Posted
技术标签:
【中文标题】是否可以使用 PhantomJS 和 Node 从模板动态生成 PDF?【英文标题】:Is it possible to use PhantomJS and Node to dynamically generate PDFs from templates? 【发布时间】:2013-10-30 06:08:52 【问题描述】:背景/需要
我正在与一个使用 Node.JS 和 Express 的 Web 应用程序的小组合作。我们需要能够生成可以打印为硬拷贝和硬拷贝表格的报告。最好我们希望在服务器上为报告和手写表单动态生成 PDF。我们目前在服务器上使用 EJS 模板。
选项
我认为能够使用模板来构建表单/报告并从生成的 html 生成 PDF 会很方便,但是据我所知,我执行此操作的选项似乎有限。我研究了两种不同的可能解决方案:
PhantomJS -- (npm node-phantom 模块) PDFKit编辑: 我发现了另一个 Node.JS 模块,它能够从名为 node-wkhtml 的 HTML 生成 PDF,它依赖于 wkhtmltopdf。我现在使用node-phantom
和node-wkhtml
进行比较。我已经能够使用这两种方法在 Node 服务器上生成 PDF,而且它们似乎都能满足我的需求。
我已经看到了一些使用 PhantomJS 从网站呈现 PDF 文档的示例,但是我看到的所有示例都使用 URL 并且不向其提供 HTML 字符串。我不确定我是否可以使用模板来动态生成 PDF 报告。
当收到报告请求时,我希望从 EJS 模板生成 HTML,并使用它来生成 PDF。无论如何,我是否可以使用 Phantom 在服务器上完全动态创建页面而无需发出请求?
我的另一个选择是使用允许动态生成 PDF 的 PDFkit,但它是一个类似于画布的 API,据我所知并不真正支持任何模板概念。
问题
有谁知道我是否可以使用 PhantomJS 和 Node 从模板生成的 HTML 动态生成 PDF?或者有谁知道我可以用来从我的 Node/Express 后端生成和提供可打印报告/表单的任何其他解决方案。
【问题讨论】:
【参考方案1】:EJS 似乎在 PhantomJS 中运行良好(安装 path
模块后)。要在给定 HTML 字符串的 PhantomJS 中加载页面,请执行 page.content = '<html><head>...';
。
npm install ejs
和 npm install path
,然后:
var ejs = require('ejs'),
page = require('webpage').create();
var html = ejs.render('<h1><%= title %></h1>',
title: 'wow'
);
page.content = html;
page.render('test.pdf');
phantom.exit();
(使用phantomjs
运行此脚本,而不是node
。)
【讨论】:
谢谢,我曾尝试使用控制本地 PhantomJS 安装的 (node-phantom) 在我的 Node 服务器上设置page.content
这样的设置。设置内容并呈现它没有引发错误,但是 PDF 只是一个空白页。要使用 node-phantom 设置内容,您必须使用异步函数 page.set
。【参考方案2】:
我将为尝试使用node-phantom
做类似事情的任何人发布答案。因为node-phantom
控制了PhantomJS的本地安装,所以即使对应的PhantomJS操作是同步的,它也必须对一切使用异步方法。当设置要在 PhantomJS 中呈现的页面内容时,您可以简单地执行以下操作:
page.content = '<h1>Some Markup</h1>';
page.render('page.pdf');
但是,使用 node 中的 node-phantom 模块,您必须使用 page.set
方法。这是我在下面使用的代码。
'use strict';
var phantom = require('node-phantom');
var html = '<!DOCTYPE html><html><head><title>My Webpage</title></head>' +
'<body><h1>My Webpage</h1><p>This is my webpage. I hope you like it' +
'!</body></html>';
phantom.create(function (error, ph)
ph.createPage(function (error, page)
page.set('content', html, function (error)
if (error)
console.log('Error setting content: %s', error);
else
page.render('page.pdf', function (error)
if (error) console.log('Error rendering PDF: %s', error);
);
ph.exit();
);
);
);
【讨论】:
我正在发送一个具有外部 css 的动态 html,因此使用“set”我无法将我的 css 应用于生成的 pdf。请有任何建议。【参考方案3】:这个问题的一个非常简单的解决方案是node-webshot 模块 - 您可以将原始 html 作为参数直接放入,它会直接打印 pdf。
【讨论】:
该文档提供 API 来仅生成图像,而不是 PDF。以上是关于是否可以使用 PhantomJS 和 Node 从模板动态生成 PDF?的主要内容,如果未能解决你的问题,请参考以下文章
使用 PhantomJS 和 node.js 保存和渲染网页
如何从codeception和phantomjs测试中获取当前url?