最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • node导出pdf

    正文概述 掘金(卡不通)   2021-01-19   497

    简介

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

    使用的依赖

    代码结构

    node导出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]+)__/g, function(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}"  />`
          }).join('')
          return data
        }
      },
      primary: {
        name: '首件检验记录表',
        fn(data) {
          data.pngs = data.imgs.map((item) => {
            return `<img src="${item.src}"  />`
          }).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 {
          margin: 0;
          padding: 20px;
        }
        /*  自定义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__" /></td>
          <td><img class="sign" src="__host__" /></td>
          <td><img class="sign" src="__packaging__" /></td>
          <td><img class="sign" src="__quality__" /></td>
          <td><img class="sign" src="__generationWorkshopDirector__" /></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 下载

    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开发环境都拥有字体库并支持中文。 但部署在服务器时,可能没有安装字体库。根据操作系统来安装中文字体库,网上可以直接搜索:

    就不展开了

    最后

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


    起源地下载网 » node导出pdf

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元