# PhantomJs打印组件
# 功能介绍
由于PhantomJS使用了一个真实的布局和渲染引擎-WebKit,因此它可以对一个网页进行截屏。因为PhantomJS可以在web页面上捕捉任何东西,所以它不仅可以用来转换带有CSS的HTML内容,还可以用来转换SVG、图像和画布元素。本功能采用了phantomjs网页截屏功能实现对加载的网页进行截屏,开发只需要编写需要打印的页面,将页面的访问地址传入封装好的方法,此功能即可对应答页面进行截屏生成base64字符串的图片或者pdf文件。
# 实现思路
通过java后台封装phantomjs能够识别的命令字符串,将参数封装到命令中,通过java后台执行命令字符串,实现对网页的截图功能
# 适配范围
此功能实现了对公文、协同、CAP3这三个业务的表单、附言、意见区域的打印,开发可以根据参数来控制要打印的区域。
# 涉及工程
涉及到的工程apps-collaboration、apps-edoc、ctp-common
# 调用说明
网页转PDF可调用ctp-common工程中的ScreenShotManager接口的htmlToPdf方法,此方法包含两个参数说明如下:
1)、url:需要打印的页面地址,开发可自己定义要打印的页面地址
公文、CAP3地址如下:
/govdoc/govdoc.do?method=showPrintForm&openFrom=listDone&affairId=xxxx&isShowComment=false&isReplyContent=false
协同地址为如下:
/collaboration/collaboration.do?method=showPrintForm&openFrom=listDone&affairId=xxxx&isShowComment=false&isReplyContent=false
url中参数说明:
isShowComment 是否显示意见区域 非必填
isReplyContent 是否显示附言信息 非必填
affairId 个人事项ID 必填
openFrom 打开类型 必填
2)、paramObj:ScreenShotParam对象,包含如下属性
sessionParams session参数
height 截屏高度
width 截屏宽度
filePath 文件存储地址,默认存储地址为base/temporary文件夹下面
renderType 渲染类型,转pdf无需设置,会强制设置为pdf类型
extParams 扩展参数,可设置转pdf的纸张格式、缩放比例等
网页转图片可调用ctp-common工程中的ScreenShotManager接口的htmlToFile方法,此方法包含的参数同htmlToPdf方法。
示例如下:
phantomjs 是 一个基于 webkit 内核的无头浏览器,提供了 javascript API接口,可以通过 js 直接与 webkit内核交互,因此我们实现了一个js文件与浏览器进行交互,此文件为ctp-common工程中的screenShot.js,java后台生成的命令与screenShot.js进行交互,screenShot.js获取后台传递的参数可以设置打印的相关参数。加载页面也可以通过collPhantom()函数与screenShot.js进行交互,从而控制截屏的效果。
screenShot.js可以获取java后台封装的命令行参数供页面截屏使用,关键方法说明如下:
page.open()此方法为页面打开的时候调用,可以设置pdf文件的的格式、缩放率、图片的渲染方式等。
page.onCallback()此函数页面调用callPhantom(obj)的时候触发,用语页面与phantomjs工具进行交互,此方法可用语动态控制截屏页面的大小,页面加载完成后返回页面对高度和宽度。
page.onCallback = function(data) {
//来自应用页面的回调,如果页面需要返回高宽则传入参数即可
if(data.height && data.width){
page.viewportSize = {
height : data.height,
width : data.width
};
}
flagData = data;
}
page.open(params.url, function(status){
if (status !== "success") {
console.info("PHANTOMJS_ERROR: Unable to open " + params.url);
phantom.exit();
}
var start = Date.now(), timeout = 10 * 1000;
var interval = setInterval(function(){
//应用页面回调后执行
if (Date.now() - start > timeout || flagData) {
clearInterval(interval);
if(params.renderType == "pdf"){
page.settings.userAgent = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 phantomJs Safari/537.36';
//如果非也参数部位空就设置分页参数,如果为空默认未A4、纵向、边距0.8cm
if(params.paperSize){
page.paperSize =params.paperSize;
}else{
page.paperSize = { format: 'A4', orientation: 'portrait', margin: '0.8cm' };
}
//如果缩放率参数不为空就设置缩放率参数,否则默认不缩放
if(params.zoomFactor){
page.zoomFactor = params.zoomFactor;
}else{
page.zoomFactor=1;
}
console.info(page.render(params.filePath));
}else{
console.info(page.renderBase64('PNG'));
}
phantom.exit();
}
}, 1000);
});
# 常见问题
转换的pdf无法分页的时候,需要设置一下网页<body>标签的高度,确保body高度和可见内容一致。
转换的pdf内容未在正中的时候,需要设置一下网页<body>标签的宽度,确保body的宽度不小于pdf内容区域的最小宽度。
转换的pdf出现内容不全,原因是phantomjs接收到的宽度、高度和页面渲染的不一致,需要确保在页面渲染完成后再调用window.callPhantom({width:width,height:height})方法想phantomjs传递高度和宽度。
在异步线程中调用表单转pdf会出现seeionid无法获取的问题,解决方案:通过后台管理员在REST用户管理模块创建一个REST用户,当出现无法获取到seeionid的时候可通过这个rest用户获取到一个固定用户的seeionid。