ITextRenderers html生成pdf 分页+横向
1.pdf横向生成问题:格式化html是加上
@page{size:297mm 210mm;}
public static String formatPdfHtml(String html,String direction) { try { StringBuilder htmlStr = new StringBuilder(); htmlStr.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"); htmlStr.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">"); htmlStr.append("<head>"); htmlStr.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"); htmlStr.append("${style_text}"); htmlStr.append("</head>"); htmlStr.append("<body>"); htmlStr.append("${content_text}"); htmlStr.append("</body>"); htmlStr.append("</html>"); StringBuilder styleStr = new StringBuilder(); StringBuilder styleBody = new StringBuilder(); styleStr.append("<style type=\"text/css\" ce_bogus=\"1\">"); if(StringUtils.isNotBlank(direction) && direction.equals("h")){ styleStr.append("@page{size:297mm 210mm;} body {font-family: Arial Unicode MS;font-size: 16px;}"); }else{ styleStr.append(" body {font-family: Arial Unicode MS;font-size: 16px;}"); } Document docHtml = Jsoup.parse(html); Elements styles = docHtml.getElementsByTag("style"); for (Element style : styles) { String[] allStyle = StringUtils.split(style.html(), "}"); for (String s : allStyle) { String[] styleOne = StringUtils.split(s, "{"); String[] body = StringUtils.split(styleOne[1], ";"); styleBody.setLength(0); for (String s1 : body) { styleBody.append(StringUtils.trim(s1) + ";"); } s = StringUtils.trim(styleOne[0]) + "{" + styleBody.toString() + "}"; s = StringUtils.replace(s, ";;", ";"); //System.out.println(s); if (!StringUtils.containsIgnoreCase(styleStr.toString(), s)) { styleStr.append(s + "\r\n"); //重复的样式不再添加 } } } styleStr.append("</style>"); Elements allelements = docHtml.getAllElements(); updateAttributes(allelements); Iterator<Element> styleIterator = styles.iterator(); while (styleIterator.hasNext()) { Element element = styleIterator.next(); //将body里面的style样式【类】全部删掉 element.remove(); } StringBuilder cssStr = new StringBuilder(); Elements elements = docHtml.select("[style]"); //获取所有元素上的样式【属性】 Iterator<Element> iterator = elements.iterator(); while (iterator.hasNext()) { cssStr.setLength(0); Element element = iterator.next(); String style = element.attr("style"); if (StringUtils.isNotBlank(style)) { style = StringUtils.trim(style); String[] ss1 = StringUtils.split(style, ";"); for (String s : ss1) { cssStr.append(s + ";"); } element.removeAttr("style"); element.attr("style", cssStr.toString()); } } docHtml.outputSettings(new Document.OutputSettings().syntax(Document.OutputSettings.Syntax.xml)); String newHtml = StringUtils.replace(htmlStr.toString(), "${content_text}", docHtml.body().html()); newHtml = StringUtils.replace(newHtml, "${style_text}", styleStr.toString()); newHtml = StringUtils.replace(newHtml, " ", ""); return newHtml; } catch (Exception e) { e.printStackTrace(); } return html; }
2.分页问题,生成html是在需要分页的地方加上
<div class='page_break_div' style='page-break-after: always'></div>
分页js
/** * html生成pdf分页 * html格式化之前不能隐藏 * 如需每页都有head或者foot 将head放入<thead></thead> 将foot放入<tfoot></tfoot> * 分页代码:<div class='page_break_div' style='page-break-after: always'></div> */ /*var page_head = ""; //每页的头部 $(".page_head").each(function () { page_head = $(this); }); var page_foot = ""; $(".page_foot").each(function () { page_foot = page_foot + $(this); });*/ /** * 遍历原数据表格,按高度生成新表格 * */ $(".pdf_data_table").each(function () { var table = $(this); var direction = $(this).attr("direction") var page_height = ''; //每页的高度 默认500px if (direction == '') { direction = 'v'; } if (page_height == '') { if (direction == 'v') { page_height = 900; //word纸张方向 竖=500 横=450 } else { page_height = 650; //word纸张方向 竖=500 横=450 } } var tbody = table.find("tbody"); var maxIndex = tbody.find("tr").length - 1; var tempTable = null; var tempHeight = 0 tbody.find("tr").each(function (index) { var tr = $(this); if (index == 0) { tempTable = createDivAndTable(table); tempTable.find("tbody").append(tr.clone()); tempHeight = tempTable.height() } else { /*if (page_head != '') { tempHeight = tempHeight + page_head.height(); }*/ tempHeight = tempHeight + tr.height(); /*if (page_foot != '') { tempHeight = tempHeight + page_foot.height(); }*/ if (tempHeight > page_height) { tempTable = createDivAndTable(table); tempTable.find("tbody").append(tr.clone()); tempHeight = 0 } else { tempTable.find("tbody").append(tr.clone()); } } }); $("#content").hide(); }); //data_div为原来html位置 $("#data_div").remove(); //移除旧表格 $('.page_break_div:last').remove(); //删除最后一个表格分页符 // $('.page_break:last').removeAttr('style'); /** * 生成新表格对象 * */ function createDivAndTable(table) { //var pageDiv = $("<div style='page-break-after:always' class='page_break'></div>"); var pageDiv = $("<div style='' class='page_break'></div>"); var div = $("<div class='page_break_div' style='page-break-after: always'></div>"); var tempTable = table.clone(); //克隆表格 var body = tempTable.find("tbody"); body.find("tr").remove(); //移除tbody中所有的tr,然后重新添加以便正确分页 /*if (page_head != '') { pageDiv.append(page_head.clone()); }*/ pageDiv.append(tempTable); /*if (page_foot != '') { pageDiv.append(page_foot.clone()); }*/ pageDiv.append(div); //格式话之后html的位置 $("#data_div_new").append(pageDiv); return tempTable; }
demo
html(freemarker)
<div class="layui-col-xs12" style="margin-top: 15px;" > <div class="layui-card" id="content"> <div class="layui-card-body"> <div class="layui-row"> <div class="layui-col-xs12"> <div style="-webkit-tap-highlight-color:rgba(0, 0, 0, 0);overflow-x:auto;min-height:0.01%;" id="data_div"> <table class="pdf_data_table" direction="h" style="padding:0px;font-size:14px;border-spacing:0px;width:100%;word-wrap:break-word;"> <thead> <tr style="text-align: center"> <td style="box-sizing:border-box;margin:0px;padding:6px;border:0px;" colspan="${psgzmxes?size+3}"> <span style="font-size: 18px"><b>技术评分表</b></span> </td> </tr> <tr style="height: 15px;"> <td style="box-sizing:border-box;margin:0px;padding:6px;border:0px;" colspan="${psgzmxes?size+3}"> <span>项目名称:${xm.name!}</span> <span style="float: right">项目编号:${xm.code!}</span> </td> </tr> <tr style="height: 15px;"> <td style="box-sizing:border-box;margin:0px;padding:6px;border:0px;" colspan="${psgzmxes?size+3}"> <span>开标时间:${xm.kbdate?string('yyyy-MM-dd HH:mm')}</span> <span style="float: right">标包名称:${bd.bdname!}</span> </td> </tr> <tr style="text-align: center"> <td rowspan="2" style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 40px"> 序号 </td> <td rowspan="2" style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 280px;"> 供应商名称 </td> <td colspan="${psgzmxes?size}" style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;"> 技术部分(${jsscoresum}分) </td> <td rowspan="2" style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 150px"> 合计得分 </td> </tr> <tr style="text-align: center"> <#list psgzmxes as mx> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: ${800/psgzmxes?size}px">${mx.pscontent} <br/>(${mx.highestscore?string('0.00')}分) </td> </#list> </tr> </thead> <tbody> <#list psTbrList as tbr> <tr style="text-align: center"> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 40px">${tbr_index+1}</td> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 280px;">${(tbr.tbr.ztname)!}</td> <#list psgzmxes as mx> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: ${800/psgzmxes?size}px"> <#list zjdfList as df> <#if df.psgzmxid== mx.id && df.pbpstbrid==tbr.id> <#if df.score??>${df.score?string('0.00')}</#if> </#if> </#list> </td> </#list> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 150px"><#if (tbr.score)??>${tbr.score?string('0.00')}</#if></td> </tr> </#list> <#list psTbrList as tbr> <tr style="text-align: center"> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 40px">${tbr_index+1}</td> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 280px;">${(tbr.tbr.ztname)!}</td> <#list psgzmxes as mx> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: ${800/psgzmxes?size}px"> <#list zjdfList as df> <#if df.psgzmxid== mx.id && df.pbpstbrid==tbr.id> <#if df.score??>${df.score?string('0.00')}</#if> </#if> </#list> </td> </#list> <td style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;width: 150px"><#if (tbr.score)??>${tbr.score?string('0.00')}</#if></td> </tr> </#list> <tr style="height: 100px"> <td colspan="${psgzmxes?size+3}" style="box-sizing:border-box;margin:0px;padding:6px;border: 1px solid;font-size: 18px;"> 专家签字: <span style="color: #ffffff">${psTbrList[0].psrname}(签名)</span></td> </tr> </tbody> <tfoot></tfoot> </table> </div> <div id="data_div_new"></div> </div> </div> </div> </div> </div>
java生成代码
public static FileBean html2pdf(FileBean fileBean,String content,String watermark,String direction) throws Exception { String fileName = PrimaryKeyUtils.genPrimaryKey(); content = HtmlUtils.formatPdfHtml(content,direction); try { ByteArrayOutputStream os = new ByteArrayOutputStream(); ITextRenderer renderer = new ITextRenderer(); ITextFontResolver fontResolver = (ITextFontResolver) renderer.getSharedContext().getFontResolver(); //添加字体库 begin // File f = new File("C:\\Windows\\Fonts"); File f = new File(SysCache.APP_PATH + "static" + File.separator + "resok" + File.separator + "Fonts"); if (f.isDirectory()) { File[] files = f.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { String lower = name.toLowerCase(); return lower.endsWith(".otf") || lower.endsWith(".ttf") || lower.endsWith(".ttc"); } }); for (int i = 0; i < files.length; i++) { fontResolver.addFont(files[i].getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); } } //添加字体库end renderer.setDocumentFromString(content); renderer.layout(); renderer.createPDF(os); renderer.finishPDF(); byte[] buff = os.toByteArray(); //保存到磁盘上 //FileUtil.byte2File(buff,pdfDestPath,pdfName); FileUtils.writeByteArrayToFile(new File(fileBean.getPath() + fileName + ".pdf"), buff, false); } catch (Exception e) { e.printStackTrace(); } if(StringUtils.isNotBlank(watermark)){ WatermarkUtils.addWatermark(fileBean.getPath() + fileName + ".pdf",watermark); } return FileSaveUtils.upLoadOther(fileBean.getPath() + fileName + ".pdf"); }