node导出pdf

1,739 阅读2分钟

简介

需求: app中填写表单(大量图片)传给后端,生成pdf返回保存于手机中

使用的依赖

html-pdf

代码结构

utils/index.js主要方法

const path = require('path')
const pdf = require('html-pdf'); // html-pdf
const optionDefault = {
  "format"'A4',
  "header": {
    "height""10mm",
    "contents"''
  },
  // "phantomPath": "/usr/local/phantomjs-2.1.1-linux-x86_64/bin/phantomjs" // 线上部署phantomjs路径
};
module.exports = {
  /**
   * 导出pdf
   * @param {String} template 模板
   * @param {String} name pdf名称
   * @param {Object} data 数据
   * @param {Function} fn 处理函数
   * @param {Object} options html-pdf参数
   */
  exportPdf(template, name, data, fn = null,  options = optionDefault) {
    return new Promise((resolve, reject) => {
      let dataReplace = { ...data };
      if (fn) { dataReplace = fn(data) }
      const html = template.replace(/__([A-Za-z]+)__/gfunction(a1, a2) {
        return dataReplace[a2] || '  '
      });
      const exportPath = path.resolve(__dirname, '../../temporary')
      pdf.create(html, options).toFile(`${exportPath}/${name}.pdf`(err, res) => {
        if (err) {
          reject(err)
        } else {
          // resolve(res)
          resolve(`${name}.pdf`)
        }
      });
    })
  },
}

enum.js 针对不同模板,编写不同处理函数

const fs = require('fs');
const path = require('path')
const TABLE_TYPE = {
  proofing: {
    name'打样单',
    fn(data) {
      data.images = data.imgs.map((item) => {
        return `<img src="${item.src}" alt="" />`
      }).join('')
      return data
    }
  },
  primary: {
    name'首件检验记录表',
    fn(data) {
      data.images = data.imgs.map((item) => {
        return `<img src="${item.src}" alt="" />`
      }).join('')
      return data
    }
  },
}
module.exports = function(type) {
  const templatePath = path.resolve(__dirname, `./template/${type}.html`)
  const template = fs.readFileSync(templatePath, 'utf8'); // 引入html模板
  const { name, fn } = TABLE_TYPE[type]
  return { name, fn , template }
}

index.js 项目启动文件


const Koa = require('koa')
const Route = require('koa-router')
const koaBody = require('koa-body')
const koaStatic = require('koa-static');
const cors = require('@koa/cors');
const path = require('path')
const app = new Koa();
const router = new Route()
const { exportPdf } = require('./utils/exportPdf')
const EnumHtml = require('./enum')

// 采用中间件
app.use(koaBody());
app.use(cors());
app.use(koaStatic(path.resolve(__dirname, '../temporary')));

// 导出pdf接口
router.post('/'async (ctx) => {
  const data = ctx.request.body
  const { template, name, fn = null } = EnumHtml(data.type)
  const exportPath = await exportPdf(template, name + data.createTime, data, fn)
  ctx.body = exportPath
  ctx.status = 200
})
app.use(router.routes())
app.listen(3001)
console.log('服务运行: http://localhost:3001')

template/proofing.html 模板文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      margin0;
      padding20px;
    }
    /*  自定义pdf样式  */
  </style>
</head>
<body>
  <table>
    <tr>
      <td class="key">申请人</td>
      <td>__applicant__</td>
      <td class="key">申请日期</td>
      <td>__date__</td>
      <td class="key">申请部门</td>
      <td>__department__</td>
    </tr>
    <tr>
      <td>负责部门</td>
      <td>面板</td>
      <td>主机</td>
      <td>打包</td>
      <td>品质</td>
      <td>生产车间主任</td>
    </tr>
    <tr class="sign-block">
      <td class="key">负责人签字</td>
      <td><img class="sign" src="__panel__" alt=""/></td>
      <td><img class="sign" src="__host__" alt=""/></td>
      <td><img class="sign" src="__packaging__" alt=""/></td>
      <td><img class="sign" src="__quality__" alt=""/></td>
      <td><img class="sign" src="__generationWorkshopDirector__" alt=""/></td>
    </tr>
  </table>
  <div class="image-block">
    <!-- 拍照信息 -->
    __images__
  </div>
</body>
</html>

问题解决

安装phantomjs

AssertionError [ERR_ASSERTION]: html-pdf: Failed to load PhantomJS module. You have to set the path to the PhantomJS binary using 'options.phantomPath'
...

小伙伴在使用中可能会出现以上问题

PhantomJs时一个服务器端的JavaScript API的WebKit,支持各种Web标准:DOM处理,CSS选择器,JSON,Canvas,SVG. 使用html-pdf时需根据服务器操作系统,安装 phantomjs 下载

本地开发使用的时windows系统时一般不需要设置,html-pdf依赖中会自动下载,但mac、linux系统需设置

  1. 下载,根据上面链接
  2. 安装,PhantomJs不需要安装,解压后,配置环境变量后,便可直接使用
  3. 配置, vim /etc/profile => export PATH=$PATH:/usr/local/phantomjs-2.1.1-linux-x86_64/bin 执行命令,使其生效:source /etc/profile
  4. 在 utils/index.js 中更改phantomjs路径

安装字体库 & 中文字体

小伙伴可能会遇到导出的pdf无法显示中文,在本地开发很难发现,因为mac、windows开发环境都拥有字体库并支持中文。 但部署在服务器时,可能没有安装字体库。根据操作系统来安装中文字体库,网上可以直接搜索:

Linux CentOS/Ubuntu 安装字体库  就不展开了

最后

希望能够帮助到你,以上代码很完整了,有什么问题可以一起交流哦