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"高级"特性。