85

我正在寻找创建pdf我的网站网页的可打印版本。像express.render()只将页面呈现为pdf

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

如果没有,您将如何实施?我见过一些方法谈论使用无头浏览器phantom.js,但不确定流程是什么。

4

15 回答 15

88

Extending upon Mustafa's answer.

A) Install http://phantomjs.org/ and then

B) install the phantom node module https://github.com/amir20/phantomjs-node

enter image description here

C) Here is an example of rendering a 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();
            });
        });
    });
});

Output of the PDF:

enter image description here

EDIT: Silent printing that PDF

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

于 2013-04-20T20:43:47.930 回答
23

Phantom.js是一个无头 webkit 服务器,它将加载任何网页并将其呈现在内存中,尽管您可能看不到它,但有一个屏幕捕获功能,您可以在其中将当前视图导出为 PNG、PDF 、JPEG 和 GIF。从 phantom.js 文档中查看这个示例

于 2013-01-27T21:07:46.953 回答
18

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

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

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

选项 3。@Jozzhard 回答

于 2014-08-09T02:46:34.033 回答
14

尝试使用 Puppeteer 从 HTML 创建 PDF

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

https://github.com/GoogleChrome/puppeteer

于 2018-10-03T11:55:52.240 回答
12

我找到的最佳解决方案是 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);
        }
    });
于 2016-05-31T12:54:56.100 回答
7

包裹

我用了html-pdf

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

使用 css + 图片

它考虑了css。我面临的唯一问题 - 它忽略了我的图像。我找到的解决方案是src用base64替换属性值中的url,例如

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

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

从 html 片段 + css 编译有效的 html 代码

  1. 我必须得到我html文档的一个片段(我只是在 jQuery 选择器上应用了 .html() 方法)。
  2. 然后我已经阅读了相关css文件的内容。

使用这两个值(存储在变量中htmlcss相应地)我使用模板字符串编译了一个有效的 html 代码

var htmlContent = `
<!DOCTYPE html>
<html>
  <head>
    <style>
      ${css}
    </style>
  </head>
  <body id=direct-sellers-bill>
    ${html}
  </body>
</html>`

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

于 2017-10-02T11:04:26.693 回答
6

对于那些不想在他们的服务器上安装 PhantomJS 和 Chrome/Firefox 实例的人 - 或者因为PhantomJS 项目当前已暂停,这里有一个替代方案。

您可以将转换外部化为 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
    }
);
于 2019-03-18T11:06:34.987 回答
5

从外部 URL 创建 PDF

这是对先前答案的改编,它利用html-pdf了 ,但也将其与requestify外部 URL 结合使用:

安装你的依赖

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(免费!)

于 2016-10-12T21:47:46.417 回答
1

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

这是一个简单的方法,每月 800 个请求是免费的:

var CloudmersiveConvertApiClient = require('cloudmersive-convert-api-client');
var defaultClient = CloudmersiveConvertApiClient.ApiClient.instance;

// Configure API key authorization: Apikey
var Apikey = defaultClient.authentications['Apikey'];
Apikey.apiKey = 'YOUR API KEY';



var apiInstance = new CloudmersiveConvertApiClient.ConvertWebApi();

var input = new CloudmersiveConvertApiClient.HtmlToPdfRequest(); // HtmlToPdfRequest | HTML to PDF request parameters
input.Html = "<b>Hello, world!</b>";


var callback = function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('API called successfully. Returned data: ' + data);
  }
};
apiInstance.convertWebHtmlToPdf(input, callback);

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

于 2020-09-06T00:31:57.960 回答
0

使用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' } 
});
于 2017-03-10T05:38:14.950 回答
0

除了@Jozzhart Answer,还可以制作本地html;用快递送达;并使用 phantom 从中制作 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>

结果:

在此处输入图像描述

于 2020-12-17T19:30:54.217 回答
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}}

于 2021-05-26T13:37:36.683 回答
0

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

它允许您从您在 Express 中使用的任何模板生成 PDF - Pug、Nunjucks 等等。

它依赖于 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 文档页面大小等

仅仅建立在别人的优秀作品之上。

于 2019-06-25T08:38:49.280 回答
0
const fs = require('fs')
const path = require('path')
const utils = require('util')
const puppeteer = require('puppeteer')
const hb = require('handlebars')
const readFile = utils.promisify(fs.readFile)

async function getTemplateHtml() {

    console.log("Loading template file in memory")
    try {
        const invoicePath = path.resolve("./invoice.html");
        return await readFile(invoicePath, 'utf8');
    } catch (err) {
        return Promise.reject("Could not load html template");
    }
}


async function generatePdf() {

    let data = {};

    getTemplateHtml()
        .then(async (res) => {
            // Now we have the html code of our template in res object
            // you can check by logging it on console
            // console.log(res)

            console.log("Compiing the template with handlebars")
            const template = hb.compile(res, { strict: true });
            // we have compile our code with handlebars
            const result = template(data);
            // We can use this to add dyamic data to our handlebas template at run time from database or API as per need. you can read the official doc to learn more https://handlebarsjs.com/
            const html = result;

            // we are using headless mode 
            const browser = await puppeteer.launch();
            const page = await browser.newPage()

            // We set the page content as the generated html by handlebars
            await page.setContent(html)

            // we Use pdf function to generate the pdf in the same folder as this file.
            await page.pdf({ path: 'invoice.pdf', format: 'A4' })

            await browser.close();
            console.log("PDF Generated")

        })
        .catch(err => {
            console.error(err)
        });
}

generatePdf();
于 2021-04-30T11:49:32.353 回答
-1

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

包 URL - https://www.npmjs.com/package/pdf-creator-node

于 2019-10-23T18:13:02.477 回答