puppeteer 生成 pdf

1,087 阅读1分钟

egg 自带国际化功能,是由 egg-i18n 插件提供。

搭建环境

mkdir egg-example && cd egg-example
npm init egg --type=simple
npm i


mkdir pdf
cd app && mkdir view
cd view && touch template.html

cd ./config
mkdir locale && cd locale
touch zh.js
touch en.js

安装依赖

npm install egg egg-view-nunjucks puppeteer -S
npm install egg-bin node-pdftk -D

config.default.js

config.i18n = {
  defaultLocale: 'zh',
};
config.nunjucks = {
  autoescape: false, // 设置不自动转译标签
};
config.nunjucks = {
  autoescape: false   //设置不自动转译标签
};
config.view = {
  defaultViewEngine: 'nunjucks',
  mapping: {
    '.html': 'nunjucks',
  }
}

plugin.js

exports.nunjucks = {
  enable: true,
  package: 'egg-view-nunjucks',
};

app/view/template.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{title}}</title>
</head>
<body>
  <header>
    {{header}}
  </header>
  <section>
    {{section}}
  </section>
</body>
</html>

app/controller/home.js

const puppeteer = require('puppeteer');
const { promises: { readFile, writeFile } } = require('fs');
const pdftk = require('node-pdftk');
const Controller = require('egg').Controller;
class HomeController extends Controller {
  async test_transfer() {
    const {ctx} = this
    const pdfString = await ctx.renderView(`../view/template.html`, {
      title:ctx.__('title'),
      header: ctx.__('header',{h:'我是变量'}),
      section: ctx.__('section'),
    })
    const template_path = `${process.cwd()}/app/public/test.html`
    await writeFile(template_path, pdfString, 'utf8')
    const browser = await puppeteer.launch({
      args: ['--disable-dev-shm-usage', '--no-sandbox']
    });
    const page = await browser.newPage();
    await page.goto('file://' + template_path);
    const footerTemplate = `<div 
        style="width:80%;margin:0 auto;font-size:8px;border-top:1px solid #ddd;padding:10px 0;display: flex; justify-content: space-between; ">
        <span style="">页脚</span>
        <div><span class="pageNumber">
        </span> / <span class="totalPages"></span></div>
        </div>`;
    const headerTemplate = `<div
        style="width:80%;margin:0 auto;font-size:8px;border-bottom:1px solid #ddd;padding:10px 0;display: flex; justify-content: space-between;">
        <span>页眉1</span>
        <span>页眉2</span>
        </div>`
    const options = {
      format: 'A4',
      printBackground: true,
      '-webkit-print-color-adjust': 'exact',
    }
    // 封面
    const page1 = await page.pdf({
      ...options,
      pageRanges: '1'
    })
    // 规避封面因为margin:0 导致的后面 margin 失效
    await page.addStyleTag({
      content: ".cover {display:none}"
    })
    // 后面所有的内容页
    const page2 = await page.pdf({
      ...options,
      displayHeaderFooter: true,
      headerTemplate,
      footerTemplate,
      margin: {
        top: 80,
        bottom: 80
      },
    })
    const pdfs = [page1, page2];
    const buf = await pdftk.input(pdfs).output()
    await writeFile(`${process.cwd()}/pdf/test.pdf`, buf)
    await browser.close(); 
    ctx.body = ctx.__('code')
  }
}
module.exports = HomeController;

en.js

module.exports = {
  code: 'success',
  title: 'title',
  header: 'these are some test code,<strong style="font-size:50px">{h}</strong>',
  section: 'section'
};

zh.js

module.exports = {
  code: '成功',
  title: '标题',
  header: '这是一段测试完文字,<strong style="font-size:50px">{h}</strong>',
  section: '章节'
};

需借助工具 pdftk下载pdf,下载链接如下:

www.pdflabs.com/tools/pdftk…

启动程序 npm run dev

输入http://127.0.0.1:7001/,如果看到success或者成功就ok了,打开 pdf 下的 test.pdf 查看生成的 pdf。