基于Phantomjs生成PDF的实现方法


Posted in Javascript onNovember 07, 2016

本文实例讲述了基于Phantomjs生成PDF的实现方法。分享给大家供大家参考,具体如下:

最近在node.js项目开发中,遇见生成PDF的需求,当然生成PDF不是一个新意的需求;我可以选择利用开源的pdfkit或者其他node pdf模块,或者通过edge.js调用.net/python下的pdf库去做生成pdf。但是在我看来对于这些东西不管如何也需要花费我们太多的时间(pdf报表的内容报表很复杂),不如把所有的画图实现逻辑推向大家所熟悉的html+css来的简洁,快速,这样对于pdf格式变化和图形计算逻辑的变化推到ejs、jade之类的模板引擎,对于以后的修改维护扩展是个很不错的选择。所以选择phantomjs加载页面生成PDF对于我来说不是个不错的选择,同时对于html+css我所需要兼容的仅有webkit一种浏览器,没有厌恶的浏览器兼容性顾虑。所以说做就做,我在项目上花了半个小时配置phantomjs的自动化脚本(在各环境能够自动勾践),以及实现了一个简单页面的PDF转化。

rasterize.js(来自官方pdf demo):

var page = require('webpage').create(),
    system = require('system'),
    address, output, size;
  if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
    console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
    phantom.exit(1);
  } else {
    address = system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 600, height: 600 };
    if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
      size = system.args[3].split('*');
      page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
        : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
    }
    if (system.args.length > 4) {
      page.zoomFactor = system.args[4];
    }
    page.open(address, function (status) {
      if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
      } else {
        window.setTimeout(function () {
          page.render(output);
          phantom.exit();
        });
      }
    });
  }

在node调用端,使用exec调用命令行输入得到文件并返回到node response流:

guid utils:

'use strict';
  var guid = function () {
    var uid = 0;
    this.newId = function () {
      uid = uid % 1000;
      var now = new Date();
      var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
      return utc.getTime() + uid++;
    }
  }
  exports.utils = {
    guid: new guid()
  };

pdfutil:

'use strict';
  var exec = require('child_process').exec;
  var utils = require('./utils').utils;
  var nodeUtil = require('util');
  var outPut = function (id, req, res) {
    var path = nodeUtil.format("tmp/%s.pdf", utils.guid.newId());
    var port = req.app.settings.port;
    var pdfUrl = nodeUtil.format("%s://%s%s/pdf/%s", req.protocol, req.host, ( port == 80 || port == 443 ? '' : ':' + port ), id);
    exec(nodeUtil.format("phantomjs tool/rasterize.js %s %s A4", pdfUrl, path), function (error, stdout, stderr) {
      if (error || stderr) {
        res.send(500, error || stderr);
        return;
      }
      res.set('Content-Type', 'application/pdf');
      res.download(path);
    });
  };
  exports.pdfUtils = {
    outPut: outPut
  };

响应的代码也可以很好的转换为java/c#...的命令行调用来得到pdf并推送到response流中。一切都这么简单搞定。

node也有node-phantom模块,但是用它生成的pdf样式有点怪,所以最后还是坚持采用了exec方式去做。

还有就是phantomjs生成PDF不会把css的背景色和背景图片带进去,所以对于这块专门利用了纯色图片img标签,并position:relative或者absolute去定位文字.这点还好因为这个页面上用户不会看的。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
基于prototype的validation.js发布2.3.4新版本,让你彻底脱离表单验证的烦恼
Dec 06 Javascript
用JavaScript实现单继承和多继承的简单方法
Mar 29 Javascript
关于jquery动态增减控件的一些想法和小插件
Aug 01 Javascript
jQuery.autocomplete 支持中文输入(firefox)修正方法
Mar 10 Javascript
实现非常简单的js双向数据绑定
Nov 06 Javascript
javascript事件处理模型实例说明
May 31 Javascript
JQuery遍历元素的后代和同胞实现方法
Sep 18 Javascript
ES6中Math对象新增的方法实例详解
Apr 25 Javascript
Array数组对象中的forEach、map、filter及reduce详析
Aug 02 Javascript
JavaScript实现答题评分功能页面
Jun 24 Javascript
解决vant title-active-color与title-inactive-color不生效问题
Nov 03 Javascript
原生js实现九宫格拖拽换位
Jan 26 Javascript
扩展Bootstrap Tooltip插件使其可交互的方法
Nov 07 #Javascript
js提示框替代系统alert,自动关闭alert对话框的实现方法
Nov 07 #Javascript
jQuery插件WebUploader实现文件上传
Nov 07 #Javascript
jQuery利用sort对DOM元素进行排序操作
Nov 07 #Javascript
AngularJS的ng Http Request与response格式转换方法
Nov 07 #Javascript
easyUI实现(alert)提示框自动关闭的实例代码
Nov 07 #Javascript
AngularJS ng-template寄宿方式用法分析
Nov 07 #Javascript
You might like
网站当前的在线人数
2006/10/09 PHP
PHP实现数字补零功能的2个函数介绍
2014/05/12 PHP
PHP5.5.15+Apache2.4.10+MySQL5.6.20配置方法分享
2016/05/06 PHP
php+mysql实现的二级联动菜单效果详解
2016/05/10 PHP
Thinkphp连表查询及数据导出方法示例
2016/10/15 PHP
php文件上传、下载和删除示例
2020/08/28 PHP
PHP中递归的实现实例详解
2017/11/14 PHP
jquery 图片预加载 自动等比例缩放插件
2008/12/25 Javascript
js的逻辑运算符 ||
2010/05/31 Javascript
javascript Array.prototype.slice使用说明
2010/10/11 Javascript
浅谈jQuery中setInterval()方法
2015/07/07 Javascript
Java Mybatis框架入门基础教程
2015/09/21 Javascript
jquery 获取select数组与name数组长度的实现代码
2016/06/20 Javascript
浅谈jQuery双事件多重加载的问题
2016/10/05 Javascript
vue实现组件之间传值功能示例
2018/07/13 Javascript
React Router V4使用指南(精讲)
2018/09/17 Javascript
vue环形进度条组件实例应用
2018/10/10 Javascript
微信小程序接入腾讯云验证码的方法步骤
2020/01/07 Javascript
微信小程序去除左上角返回键的实现方法
2020/03/06 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
Python中如何导入类示例详解
2019/04/17 Python
Python玩转加密的技巧【推荐】
2019/05/13 Python
通过pycharm使用git的步骤(图文详解)
2019/06/13 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
美国男士西装打折店:Jos. A. Bank
2017/11/13 全球购物
Airbnb爱彼迎官网:成为爱彼迎房东,赚取收入
2019/03/14 全球购物
Senreve官网:美国旧金山的奢侈手袋品牌
2019/03/21 全球购物
C语言中break与continue的区别
2012/07/12 面试题
Python里面如何实现tuple和list的转换
2012/06/13 面试题
大一自我鉴定范文
2013/10/04 职场文书
兼职学生的自我评价
2013/11/24 职场文书
财产公证书格式
2014/04/10 职场文书
高中校园广播稿3篇
2014/09/29 职场文书
公积金具结保证书
2015/05/11 职场文书
ThinkPHP5和ThinkPHP6的区别
2021/03/31 PHP
简单聊聊Golang中defer预计算参数
2022/03/25 Golang