我正在尝试使用Google Chrome替代PhantomJS将HTML呈现为PDF。到目前为止,它对我来说一直很好。我唯一的问题是我没有找到任何方法来翻译以下PhantomJS代码:
page.paperSize = {
footer: {
contents: phantom.callback(function(pageNum, numPages) {
return "Power by MyWebsite. Created on "+formatDate(new Date())+"<span style='float:right'>" + pageNum + " / " + numPages + "</span>";
})
}
}
格式日期与问题How to format a JavaScript date
中的功能相同但是,我还没有找到一种方法来在谷歌Chrome中无头复制这种行为。 我正在使用https://github.com/cyrus-and/chrome-remote-interface
中的Chrome远程接口(CDP)这是我的chrome远程接口代码的概述:
return new Promise(async function (resolve, reject) {
const url = "<MyURL here>";
const [tab] = await Cdp.List()
const client = await Cdp({ host: '127.0.0.1', target: tab });
await Promise.all([
Network.enable(),
Page.enable()
]);
Page.loadEventFired(function () {
setTimeout(function () {
resolve(Page.printToPDF({displayHeaderFooter:true}))); //https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
}, 3000);
});
await Page.navigate({ url });
};
我正在使用PDF,但只能获得默认的Chrome页眉和页脚。有什么方法可以修改它们吗?
注意:我意识到我可以在页面中使用JavaScript将元素附加到每个页面的底部,但我更喜欢在导出时更改浏览器附加的页脚打印,因为我发现正确放置并且不会导致页面中其他div的任何奇怪的重新流动更加可靠。
答案 0 :(得分:12)
可以使用<header>
和<footer>
标记创建自定义页眉和页脚。我使用它来使用Chrome Headless生成PDF。我还没有在Firefox,IE等中测试过它......
<header>
Custom Header
<img src="http://imageurl.com/image.jpg"/>
</header>
<div class="content">Page Content - as long as you want</div>
<footer>
Footer Content
</footer>
CSS
@page {
margin: 0;
}
@media print {
footer {
position: fixed;
bottom: 0;
}
header {
position: fixed;
top: 0;
}
}
@page { margin: 0 }
删除默认的页眉和页脚。
希望这会有所帮助。
答案 1 :(得分:12)
这是对问题的更新/回答。从Chromium 64开始,可以使用headerTemplate
和footerTemplate
参数printToPDF
使用chrome remote interface这里应该有效的示例代码:
return new Promise(async function (resolve, reject) {
const url = "<MyURL here>";
const [tab] = await Cdp.List()
const client = await Cdp({ host: '127.0.0.1', target: tab });
await Promise.all([
Network.enable(),
Page.enable()
]);
Page.loadEventFired(function () {
setTimeout(function () {
//https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
resolve(Page.printToPDF({
displayHeaderFooter:true,
footerTemplate: "<span class='pageNumber'> of <span class='totalPages'>"
})));
}, 3000);
});
await Page.navigate({ url });
};
答案 2 :(得分:8)
您的问题有两种解决方案
A)通过不留余量推出chrome-header:
@page {
margin: 0;
size: auto;
}
或
@media print {
@page { margin: 0; }
body { margin: 1.6cm; }
}
B)最初是一个适用于Chrome的Firefox解决方案
<html moznomarginboxes mozdisallowselectionprint>
一些样本:
<!DOCTYPE html>
<html moznomarginboxes mozdisallowselectionprint>
<head>
<title>Print PDF without header</title>
<style>
@media print {
@page { margin: 0; }
body { margin: 1.6cm; }
}
</style>
</head>
<body>
<p>Some Text in Paragraph to print!</p>
<a href="javascript:print()">Print</a>
</body>
</html>
答案 3 :(得分:3)
根据this forum,目前无法在Google Chrome中执行此操作。您所能做的就是打开或关闭页眉/页脚。这由评论表示:
目前,在打印文档时无法编辑标题。您当前只能打开或关闭页眉和页脚,其中包括日期,网页名称,页面URL以及您要打印的文档的页数。您可能需要查看Chrome网上应用店,看看是否有任何方便的第三方扩展程序,您可以在Chrome上安装这些扩展程序,这些扩展程序可能符合您在打印方面的要求 - Source
可能有第三方扩展程序可以获取您要查找的功能,或者按照您的建议,您可以使用JavaScript附加要打印的元素。
答案 4 :(得分:2)
如果你真的想以一种非hacky的方式做这件事,你必须得到chrome devtools协议,因为命令行界面不支持太多(aka --print-to-pdf
就是你得到的,没有打印选项)
此处记录了协议:https://chromedevtools.github.io/devtools-protocol/tot
客户端库提供多种语言版本,可通过包管理器获得。
以下是我用于演示用法的一些示例:
Page.printToPDF
协议方法支持为页眉和页脚传递自定义标记的参数。
基本上,协议是在protocol.json
中定义的,客户端库使用它来生成在任何应用程序中使用的类/方法。这些方法将较低级别的通信封装在协议中。
我所要做的就是安装一个客户端库包(通过npm或composer),确保安装了chrome,写了一些代码,然后生成没有页眉/页脚的pdf!奇妙。
答案 5 :(得分:2)
正如亚历克·雅各布森(Alec Jacobson)在评论中提到的那样,在页面上使用margin:0以及在正文上使用margin:1.6cm仅适用于一页。
对我有用的是将内容包装在表格中,顶部使用thead,底部使用tfoot。 Thead和tfoot在所有页面上重复,并且您的主页内容位于表格的正文中。
示例:
`
<thead>
<tr>
<th style="height: 1cm">
Header
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Page Content
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td style="height: 1cm">
Footer
</td>
</tr>
</tfoot>
</table>`
本来希望添加到评论主题中,但信誉不够。
答案 6 :(得分:1)
对于那些只想要开箱即用的东西的人,我想分享我今天根据apokryfos的回答编写的脚本。
首先,您需要安装依赖项
yarn global add chrome-remote-interface
接下来,您需要在启用调试端口的情况下启动无头铬
chromium-browser --headless --disable-gpu --run-all-compositor-stages-before-draw --remote-debugging-port=9222
现在您必须将我的脚本保存为print-via-chrome.js
:
#!/usr/bin/env node
const homedir = require('os').homedir();
const CDP = require(homedir+'/.config/yarn/global/node_modules/chrome-remote-interface/');
const fs = require('fs');
const port = process.argv[2];
const htmlFilePath = process.argv[3];
const pdfFilePath = process.argv[4];
(async function() {
const protocol = await CDP({port: port});
// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page} = protocol;
await Page.enable();
Page.loadEventFired(function () {
console.log("Waiting 100ms just to be sure.")
setTimeout(function () {
//https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
console.log("Printing...")
Page.printToPDF({
displayHeaderFooter: true,
headerTemplate: '<div></div>',
footerTemplate: '<div class="text center"><span class="pageNumber"></span></div>',
//footerTemplate: '<div class="text center"><span class="pageNumber"></span> of <span class="totalPages"></span></div>'
}).then((base64EncodedPdf) => {
fs.writeFileSync(pdfFilePath, Buffer.from(base64EncodedPdf.data, 'base64'), 'utf8');
console.log("Done")
protocol.close();
});
}, 100);
});
Page.navigate({url: 'file://'+htmlFilePath});
})();
使用chmod +x print-via-chrome.js
使其可执行后,您应该能够将html文件转换为pdf文件,如下所示:
./print-via-chrome.js 9222 my.html my.pdf
完成转化后,别忘了去除铬。
我很确定该解决方案还远远不够完美,但是至少它能起作用,而且由于我看到了很多有关此功能的问题,我不得不花自己的几个小时来使它起作用,我想分享一下我的解决方案。我遇到的一些问题与header-和footerTemplates有关,因为空模板似乎无法代替现有模板(您需要<div></div>
),而在文档中有不同说明的情况下,新模板不会出现在可见区域中,直到用<div class="text center">
或类似的符号包裹。