# 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方法。

示例如下:

1696655665(1)

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);
});

# 常见问题

  1. 转换的pdf无法分页的时候,需要设置一下网页<body>标签的高度,确保body高度和可见内容一致。

  2. 转换的pdf内容未在正中的时候,需要设置一下网页<body>标签的宽度,确保body的宽度不小于pdf内容区域的最小宽度。

  3. 转换的pdf出现内容不全,原因是phantomjs接收到的宽度、高度和页面渲染的不一致,需要确保在页面渲染完成后再调用window.callPhantom({width:width,height:height})方法想phantomjs传递高度和宽度。

  4. 在异步线程中调用表单转pdf会出现seeionid无法获取的问题,解决方案:通过后台管理员在REST用户管理模块创建一个REST用户,当出现无法获取到seeionid的时候可通过这个rest用户获取到一个固定用户的seeionid。

创建人:ranjunfeng
修改人:ranjf、admin、het、lichaoj