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/ ...
随机推荐
- 我决定!墙裂推荐高清无码Python电子书(文中福利)
@ 目录 前言 视频网站学习的优点和缺点 Python基础 游戏 网站开发 前言 近几年学了Python,查阅了不少资料,如B站,慕课网,我要自学网等等,然后自己边看学书自己整理学习资料,想分享下如何 ...
- 揭秘:懂Python的测试员薪资到底有多高?
前言 面试的时候,面试官经常会问:会Python吗?有在工作中写过项目吗?会搭建自己的框架吗?我:恩,我只简单写过一些demo. 有时候问一些简单的Python,一问就会懵.比如:json和字典有什么 ...
- golang实现一个简单的websocket聊天室
基本原理: 1.引入了 golang.org/x/net/websocket 包. 2.监听端口. 3.客户端连接时,发送结构体: {"type":"login" ...
- TypeScript 条件类型精读与实践
在大多数程序中,我们必须根据输入做出决策.TypeScript 也不例外,使用条件类型可以描述输入类型与输出类型之间的关系. 本文同步首发在个人博客中,欢迎订阅.交流. 用于条件判断时的 extend ...
- 微服务安全(二)OAuth 2.0
1. 概念 OAuth是一个开放的.安全的用户认证协议,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源,而无须将用户名和登录口令提供给第三方应用.授权的第三方应用只能在特定的时段内访问特定 ...
- oracle dg failover灾难切换
oracle dg failover灾难切换SQL> alter database recover managed standby database finish force;SQL> a ...
- React Native之新架构中的Turbo Module实现原理分析
有段时间没更新博客了,之前计划由浅到深.从应用到原理,更新一些RN的相关博客.之前陆续的更新了6篇RN应用的相关博客(传送门),后边因时间问题没有继续更新.主要是平时空余时间都用来帮着带娃了,不过还是 ...
- 魔改swagger:knife4j的另外一种打开方式
之前公司使用了swagger作为文档管理工具,原生的swagger-ui非常丑,之后就用了开源项目 萧明 / knife4j 的swagger组件进行了swagger渲染,改造之后界面漂亮多了,操作也 ...
- 搭建Mac+Java+appium+IOS真机自动化环境
一.安装前环境准备 1.确保电脑已经有homebrew(包管理器) 下载链接[https://brew.sh/] 2.通过 brew 安装node.js brew install node 安装 ...
- DRF的action装饰器
1.action装饰器 Django默认的路由分发规则决定了视图函数只能以get.post等请求方式命名,如果想要使用自定义的方式命名,我们可以使用action去映射请求方法名与自定义方法 view. ...