使用Node.js将HTML转换为PDF

时间:2013-01-27 20:50:04

标签: node.js express pdf-generation

我希望创建一个可打印的pdf版本的网站网页。像express.render()这样的内容只会将页面呈现为pdf

有没有人知道这样做的节点模块?

如果没有,你会如何实施?我已经看到一些方法谈论使用无头浏览器,如phantom.js,但不确定流量是什么。

15 个答案:

答案 0 :(得分:87)

延伸到穆斯塔法的答案。

A)安装http://phantomjs.org/然后

B)安装幻像节点模块https://github.com/amir20/phantomjs-node

enter image description here

C)以下是渲染pdf

的示例
var phantom = require('phantom');   

phantom.create().then(function(ph) {
    ph.createPage().then(function(page) {
        page.open("http://www.google.com").then(function(status) {
            page.render('google.pdf').then(function() {
                console.log('Page Rendered');
                ph.exit();
            });
        });
    });
});

PDF的输出:

enter image description here

编辑: Silent printing that PDF

java -jar pdfbox-app-2.0.2.jar PrintPDF -silentPrint C:\print_mypdf.pdf

答案 1 :(得分:22)

Phantom.js是一个无头webkit服务器,它将加载任何网页并将其呈现在内存中,虽然您可能无法看到它,但有一个屏幕捕获功能,您可以在其中导出当前查看为PNG,PDF,JPEG和GIF。看看这个example from phantom.js documentation

答案 2 :(得分:13)

如果要将HTML导出为PDF。你有很多选择。没有节点甚至

选项1:在html页面上有一个调用window.print()函数的按钮。使用浏览器原生html到pdf。使用媒体查询使您的HTML页面在pdf上看起来很好。并且您还可以在事件之前和之后进行打印,以便在打印前对页面进行更改。

选项2. htmltocanvasrasterizeHTML。将html转换为canvas,然后在canvas对象上调用toDataURL()以获取图像。并使用像jsPDF这样的JavaScript库将该图像添加到PDF文件中。这种方法的缺点是pdf不可编辑。如果您想要从PDF中提取数据,可以采用不同的方法。

选项3. @Jozzhard回答

答案 3 :(得分:9)

我找到的最佳解决方案是html-pdf。这很简单,可以使用大HTML。

https://www.npmjs.com/package/html-pdf

就像那样简单:

    pdf.create(htm, options).toFile('./pdfname.pdf', function(err, res) {
        if (err) {
          console.log(err);
        }
    });

答案 4 :(得分:6)

从外部网址创建PDF

以下是使用html-pdf的先前答案的修改,但也将其与requestify结合使用,因此它适用于外部网址:

安装依赖项

npm i -S html-pdf requestify

然后,创建脚本:

//MakePDF.js

var pdf = require('html-pdf');
var requestify = require('requestify');
var externalURL= 'http://www.google.com';

requestify.get(externalURL).then(function (response) {
   // Get the raw HTML response body
   var html = response.body; 
   var config = {format: 'A4'}; // or format: 'letter' - see https://github.com/marcbachmann/node-html-pdf#options

// Create the PDF
   pdf.create(html, config).toFile('pathtooutput/generated.pdf', function (err, res) {
      if (err) return console.log(err);
      console.log(res); // { filename: '/pathtooutput/generated.pdf' }
   });
});

然后您只需从命令行运行:

node MakePDF.js

观看您的美化像素完美PDF为您创建(免费!)

答案 5 :(得分:5)

尝试使用Puppeteer从HTML创建PDF

这里的示例https://github.com/chuongtrh/html_to_pdf

https://github.com/GoogleChrome/puppeteer

答案 6 :(得分:3)

<强>封装

我使用了html-pdf

易于使用,不仅可以将pdf保存为文件,还可以将pdf内容传输到WriteStream(因此我可以将其直接流式传输到Google Storage以保存报告)。

使用css +图像

考虑到css。我遇到的唯一问题 - 它忽略了我的图像。我找到的解决方案是将src attrribute值中的url替换为base64,例如

<img src="data:image/png;base64,iVBOR...kSuQmCC">

您可以使用您的代码或使用在线转换器之一,例如https://www.base64-image.de/

从html fragment + css

编译有效的html代码
  1. 我必须得到我的html文档的片段(我只是在jQuery选择器上使用了.html()方法)。
  2. 然后,我已阅读相关css文件的内容。
  3. 使用这两个值(相应地存储在变量htmlcss中)我已使用Template string

    编译了有效的html代码
    var htmlContent = `
    <!DOCTYPE html>
    <html>
      <head>
        <style>
          ${css}
        </style>
      </head>
      <body id=direct-sellers-bill>
        ${html}
      </body>
    </html>`
    

    并将其传递给html-pdfcreate方法。

答案 7 :(得分:3)

对于那些不想在服务器上安装PhantomJS以及Chrome / Firefox实例的用户-或因为PhantomJS project is currently suspended,这是一个替代选择。

您可以将转换外部化为API来完成这项工作。许多存在并且各不相同,但是您将获得的是具有最新功能的可靠服务(我认为CSS3,Web字体,SVG,Canvas兼容)。

例如,使用PDFShift(免责声明,我是创始人),您只需使用request软件包即可做到这一点:

const request = require('request')
request.post(
    'https://api.pdfshift.io/v2/convert/',
    {
        'auth': {'user': 'your_api_key'},
        'json': {'source': 'https://www.google.com'},
        'encoding': null
    },
    (error, response, body) => {
        if (response === undefined) {
            return reject({'message': 'Invalid response from the server.', 'code': 0, 'response': response})
        }
        if (response.statusCode == 200) {
            // Do what you want with `body`, that contains the binary PDF
            // Like returning it to the client - or saving it as a file locally or on AWS S3
            return True
        }

        // Handle any errors that might have occured
    }
);

答案 8 :(得分:1)

使用 html-pdf

var fs = require('fs');
var pdf = require('html-pdf');
var html = fs.readFileSync('./test/businesscard.html', 'utf8');
var options = { format: 'Letter' };

pdf.create(html, options).toFile('./businesscard.pdf', function(err, res) {
  if (err) return console.log(err);
  console.log(res); // { filename: '/app/businesscard.pdf' } 
});

答案 9 :(得分:1)

在我看来,最好的方法是通过API,这样您就不会在运行非托管代码的应用程序中添加大型且复杂的依赖项,而该依赖项需要经常更新。

这是执行此操作的简单方法,每月可免费使用800个请求:

:plain

使用上述方法,您还可以在本地或根据需要在自己的基础结构上安装API。

答案 10 :(得分:0)

如果您到达这里,是想找一种方法从Express中的视图模板制作PDF,我和同事做了express-template-to-pdf

这使您可以从Express中使用的任何模板(Pug,Nunjucks等)生成PDF。

它取决于html-pdf,并且被编写为在路由中使用,就像您使用res.render一样:

const pdfRenderer = require('@ministryofjustice/express-template-to-pdf')

app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')

app.use(pdfRenderer())

如果您使用过res.render,那么使用它应该看起来很明显:

app.use('/pdf', (req, res) => {
    res.renderPDF('helloWorld', { message: 'Hello World!' });
})

您可以将选项传递给html-pdf,以控制PDF文档的页面大小等

仅仅依靠他人的出色工作。

答案 11 :(得分:0)

您还可以使用pdf节点创建程序包

包装网址- https://www.npmjs.com/package/pdf-creator-node

答案 12 :(得分:0)

除了@Jozzhart Answer,您还可以创建本地html;用快递服务并使用幻像从中制作PDF;像这样的东西:

const exp = require('express');
const app = exp();
const pth = require("path");
const phantom = require('phantom');
const ip = require("ip");

const PORT = 3000;
const PDF_SOURCE = "index"; //index.html
const PDF_OUTPUT = "out"; //out.pdf

const source = pth.join(__dirname, "", `${PDF_SOURCE}.html`);
const output = pth.join(__dirname, "", `${PDF_OUTPUT}.pdf`);

app.use("/" + PDF_SOURCE, exp.static(source));
app.use("/" + PDF_OUTPUT, exp.static(output));

app.listen(PORT);

let makePDF = async (fn) => {
    let local = `http://${ip.address()}:${PORT}/${PDF_SOURCE}`;
    phantom.create().then((ph) => {
        ph.createPage().then((page) => {
            page.open(local).then(() =>
                page.render(output).then(() => { ph.exit(); fn() })
            );
        });
    });
}

makePDF(() => {
    console.log("PDF Created From Local File");
    console.log("PDF is downloadable from link:");
    console.log(`http://${ip.address()}:${PORT}/${PDF_OUTPUT}`);
});

和index.html可以是任何东西:

<h1>PDF HEAD</h1>
<a href="#">LINK</a>

结果:

enter image description here

答案 13 :(得分:0)

select productid,
       sum(weight * (measurementtype - 1)) as weight_calculated,
       sum(weight * measurementtype) as weight_measured
from t
group by productid;

答案 14 :(得分:0)

https://www.npmjs.com/package/dynamic-html-pdf

我使用dynamic-html-pdf,这很简单,也可以将动态变量传递给html。

var html = fs.readFileSync('./uploads/your-html-tpl.html', 'utf8');
var options = {
    format: "A4",
    orientation: "portrait"
    // border: "10mm"
};
var document = {
    type: 'file',     // 'file' or 'buffer'
    template: html,
    context: {
       'your_key':'your_values'
    },
    path: '/pdf/1.pdf'   // pdf save path
};

pdf.create(document, options)
.then(res => {
    console.log(res)
}).catch(error => {
    console.error(error)
});

在 html 上你可以使用 {{your_key}}