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");
}
ITextRenderers html生成pdf 分页+横向的更多相关文章
- wkhtmltopdfhtml php生成pdf快照,网页截图,网页快照完整版 (原)
首先,安装(linux安装为例) 1.下载wkhtmltopdf wget http://download.gna.org/wkhtmltopdf/obsolete/linux/wkhtmltopdf ...
- C#使用wkhtmltopdf,把HTML生成PDF(包含分页)
最近花了2天多的时间终于把HTML生成PDF弄好了.步骤如下: 1.首先是技术选型.看了好多都是收费的就不考虑了. 免费的有: jsPDF(前端生成,清晰度不高,生成比较慢) iText(严格要求ht ...
- 利用Java动态生成 PDF 文档
利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...
- Java生成PDF报表
一.前言 前几天,做ASN条码收货模块,需要实现打印下载收货报表,经一番查找,选定iText--用于生成PDF文档的一个Java类库.废话不多说,进入正题. 二.iText简介 iText是著名的开放 ...
- Java生成PDF文件(转)
原文地址:https://www.cnblogs.com/shuilangyizu/p/5760928.html 一.前言 前几天,做ASN条码收货模块,需要实现打印下载收货报表,经一番查找,选定iT ...
- vue生成pdf
主要参考 https://blog.csdn.net/qq_37880968/article/details/94626001 1.添加模块 npm install --save html2canva ...
- [itext]Java生成PDF文件
一.前言 最近在做也导出试卷的功能,刚开始是导出为doc,可是导出来格式都有变化,最后说直接将word转为pdf,可是各种不稳定,各种报错.最后想到直接将文件写入pdf(参考:http://www.c ...
- [轉載]史上最强php生成pdf文件,html转pdf文件方法
之前有个客户需要把一些html页面生成pdf文件,然后我就找一些用php把html页面围成pdf文件的类.方法是可谓是找了很多很多,什么html2pdf,pdflib,FPDF这些都试过了,但是都没有 ...
- 【PDF】java使用Itext生成pdf文档--详解
[API接口] 一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/ ...
随机推荐
- P2350-[HAOI2012]外星人【线性筛】
正题 题目链接:https://www.luogu.com.cn/problem/P2350 题目大意 给出\(N\)质因数分解之后的结果,求每次\(N=\varphi(N)\),多少次后\(N=1\ ...
- Redis之品鉴之旅(一)
Redis之品鉴之旅(一) 好知识就如好酒,需要我们坐下来,静静的慢慢的去品鉴.Redis作为主流nosql数据库,在提升性能的方面是不可或缺的.下面就拿好小板凳,我们慢慢的来一一品鉴. 1)redi ...
- mysql8.0.20安装配置教程
mysql配置安装教程 1.下载mysql8.0.20安装包 下载地址: https://dev.mysql.com/downloads/mysql/.找到安装包后下载.(官网为英文,如果看不懂的小伙 ...
- 调试器地址出现大小端紊乱,引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
今天在编写一系列新增需求代码后,开始调试代码 发现上个版本正常可运行的代码出现了:引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突. 上个版本数代码 ...
- 题解 AVL 树
link Description 给出一个 \(n\) 个点的 AVL 树,求保留 \(k\) 个点使得字典序最小. \(n\le 5\times 10^5\) Solution 因为我很 sb ,所 ...
- 洛谷4400 BlueMary的旅行(分层图+最大流)
qwq 首先,我们观察到题目中提到的每天只能乘坐一次航班的限制,很容易想到建分层图,也就是通过枚举天数,然后每天加入一层新的点. (然而我一开始想的却是erf) 考虑从小到大枚举天数,然后每次新建一层 ...
- 无法获取指向控制台的文件描述符 (couldn't get a file descriptor referring to the console)
背景 最近收拾东西,从一堆杂物里翻出来尘封四年多的树莓派 3B 主机来,打扫打扫灰尘,接上电源,居然还能通过之前设置好的 VNC 连上.欣慰之余,开始 clone 我的 git 项目,为它们拓展一个新 ...
- 寻找写代码感觉(八)之SpringBoot过滤器的使用
一.什么是过滤器? 过滤器是对数据进行过滤,预处理过程,当我们访问网站时,有时候会发布一些敏感信息,发完以后有的会用*替代,还有就是登陆权限控制等,一个资源,没有经过授权,肯定是不能让用户随便访问的, ...
- beta事后分析
设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 软件要解决的问题是是开发一个简易方便,为用户带来便捷且功能齐全的表情包管理小程序: 预期的典型用户 ...
- JavaAgent型内存马基础
Java Instrumentation java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序.这种监测和协助包括但不 ...