JavaScript+Java实现HTML页面转为PDF文件保存的方法
需求是一个导出pdf的功能,多方奔走终于实现了,走了不少弯路,而且怀疑现在这个方法仍是弯的。
有个jsPDF插件可以在前端直接生成pdf,很简便,但不支持IE。
前端:
首先引入 html2canvas.js
html2canvas(document.body,{//截图对象
//此处可配置详细参数
onrendered:function(canvas){//渲染完成回调canvas
canvas.id="mycanvas";
//生成base64图片数据
vardataUrl=canvas.toDataURL('image/png');//指定格式,也可不带参数
varformData=newFormData();//模拟表单对象
formData.append("imgData",convertBase64UrlToBlob(dataUrl));//写入数据
varxhr=newXMLHttpRequest();//数据传输方法
xhr.open("POST","../bulletin/exportPdf");//配置传输方式及地址
xhr.send(formData);
xhr.onreadystatechange=function(){//回调函数
if(xhr.readyState==4){
if(xhr.status==200){
varback=JSON.parse(xhr.responseText);
if(back.success==true){
alertBox({content:'Pdf导出成功!',lock:true,drag:false,ok:true});
}else{
alertBox({content:'Pdf导出失败!',lock:true,drag:false,ok:true});
}
}
}
};
}
});
//将以base64的图片url数据转换为Blob
functionconvertBase64UrlToBlob(urlData){
//去掉url的头,并转换为byte
varbytes=window.atob(urlData.split(',')[1]);
//处理异常,将ascii码小于0的转换为大于0
varab=newArrayBuffer(bytes.length);
varia=newUint8Array(ab);
for(vari=0;i<bytes.length;i++){
ia[i]=bytes.charCodeAt(i);
}
returnnewBlob([ab],{type:'image/png'});
}
兼容性:Firefox3.5+,Chrome,Opera,IE10+
不支持:iframe,浏览器插件,Flash
跨域图片需要在跨域服务器header加上允许跨域请求
access-control-allow-origin:*access-control-allow-credentials:true
svg图片不能直接支持,已经有补丁包了,不过我没有试过。
IE9不支持FormData数据格式,也不支持Blob,这种情况下将canvas生成的64base字符串去掉url头之后直接传给后台,后台接收之后:
Stringbase64=Img.split(",")[1];
BASE64Decoderdecode=newBASE64Decoder();
byte[]imgByte=decode.decodeBuffer(base64);
后端:
导入itextjar包(官方下载地址:https://sourceforge.net/projects/itext/)
@RequestMapping("/exportPdf")
public@ResponseBodyvoidexportPdf(MultipartHttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
ResultDataresult=newResultData();//自定义结果格式
StringfilePath="c:\\exportPdf2.pdf";
StringimagePath="c:\\exportImg2.bmp";
Documentdocument=newDocument();
try{
MapgetMap=request.getFileMap();
MultipartFilemfile=(MultipartFile)getMap.get("imgData");//获取数据
InputStreamfile=mfile.getInputStream();
byte[]fileByte=FileCopyUtils.copyToByteArray(file);
FileImageOutputStreamimageOutput=newFileImageOutputStream(newFile(imagePath));//打开输入流
imageOutput.write(fileByte,0,fileByte.length);//生成本地图片文件
imageOutput.close();
PdfWriter.getInstance(document,newFileOutputStream(filePath));//itextpdf文件
//document.setPageSize(PageSize.A2);
document.open();
document.add(newParagraph("JUSTTEST..."));
Imageimage=Image.getInstance(imagePath);//itext-pdf-image
floatheigth=image.getHeight();
floatwidth=image.getWidth();
intpercent=getPercent2(heigth,width);//按比例缩小图片
image.setAlignment(Image.MIDDLE);
image.scalePercent(percent+3);
document.add(image);
document.close();
result.setSuccess(true);
operatelogService.addOperateLogInfo(request,"导出成功:成功导出简报Pdf");
}catch(DocumentExceptionde){
System.err.println(de.getMessage());
}
catch(Exceptione){
e.printStackTrace();
result.setSuccess(false);
result.setErrorMessage(e.toString());
try{
operatelogService.addOperateLogError(request,"导出失败:服务器异常");
}catch(Exceptione1){
e1.printStackTrace();
}
}
response.getWriter().print(JSONObject.fromObject(result).toString());
}
privatestaticintgetPercent2(floath,floatw){
intp=0;
floatp2=0.0f;
p2=530/w*100;
p=Math.round(p2);
returnp;
}
iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。
处理速度快,支持很多PDF"高级"特性。