需求:将网页内容导出为pdf文件,其中包含文字,图片,echarts图
原理:利用freemarker模板与数据渲染所得到的html内容,通过
ITextRenderer对象解析html内容生成pdf
参考地址:
导出pdf
带有图片
使用itext将html生成pdf中文换行问题解决方案
本文内容是参考以上地址内容对需求的实现
1.添加依赖
<!-- freemarker --> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.19</version> </dependency> <!-- itextpdf,导出pdf核心架包 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.11</version> </dependency> <!-- itextpdf工具包,用来解析html生成pdf --> <dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>5.5.11</version> </dependency> <!-- flying saucer,支持对CSS高级特性的解析 --> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.1.5</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-itext5</artifactId> <version>9.1.5</version> </dependency>
2.freemarker模板数据渲染html内容
// 获设置模板路径,供参考 static { freemarkerCfg =new Configuration(); //freemarker的模板目录 freemarkerCfg.setClassForTemplateLoading(JavaToPdfHtmlFreeMarker.class,"/"); } public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) { Writer out = new StringWriter(); try { // 获取模板,并设置编码方式 Template template = freemarkerCfg.getTemplate(htmlTmp); template.setEncoding("UTF-8"); // 合并数据模型与模板 template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流 out.flush(); return out.toString(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException ex) { ex.printStackTrace(); } } return null; }
3.解析html内容生成pdf
public static void createPdf(String content,OutputStream out) throws IOException, com.lowagie.text.DocumentException { ITextRenderer render = new ITextRenderer(); ITextFontResolver fontResolver = render.getFontResolver(); fontResolver.addFont("C:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 解析html生成pdf render.setDocumentFromString(content); //解决图片相对路径的问题 //render.getSharedContext().setBaseURL(""); render.layout(); render.createPDF(out); render.finishPDF(); }
OutputStream out可以换作其他输出流对象,比如new FileOutputStream("D:/a.pdf")
注意:设置字体后,需在CSS文件中也设置该字体,才可以显示中文
图片可以使用CSS设置背景图片为base64码格式展示
body{ font-family:SimSun; }
上面内容为网页下载pdf所调用,调用方法如下(供参考):
try{ OutputStream out = null; out = response.getOutputStream(); //设置响应对象上下文类型 response.setContentType( "application/pdf,charset=utf-8"); //文件名处理,防止乱码问题 fileName += DateTimeUtils.currentDate("yyMMddHHmmss") + ".pdf"; String filename = ""; filename = request==null? java.net.URLEncoder.encode(fileName, "UTF-8"): AppUtils.encodingFileName(fileName,request); //设置响应头 response.setHeader("Content-Disposition","attachment;filename=" + filename); JavaToPdfHtmlFreeMarker.createPdf(content,out); //获取响应对象输出流并返回 if (out != null) { out.close(); out = null; } } catch (UnsupportedEncodingException e) { e.printStackTrace(); return super.outJsonStringFail(); } catch (IOException e) { e.printStackTrace(); return super.outJsonStringFail(); } catch (com.lowagie.text.DocumentException e) { e.printStackTrace(); return super.outJsonStringFail(); }
4.如有echarts图,可添加一下js,将图转为base64码放于css或者html中的style属性中
/** * 将多个canvas画布组成的图表合成为一个完整的canvas,并获取完整的dataURl * @param divId divId 包含整个画布的divId * @returns {String} widthXheight@dataURL 例: * 400X300@data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA */ function getFullCanvasDataURL(divId){ //将第一个画布作为基准。 var baseCanvas = $("#"+divId).find("canvas").first()[0]; if(!baseCanvas){ return false; }; var width = baseCanvas.width; var height = baseCanvas.height; var ctx = baseCanvas.getContext("2d"); //遍历,将后续的画布添加到在第一个上 $("#"+divId).find("canvas").each(function(i,canvasObj){ if(i>0){ var canvasTmp = $(canvasObj)[0]; ctx.drawImage(canvasTmp,0,0,width,height); } }); //获取base64位的url return baseCanvas.toDataURL(); }