Java使用iText7生成PDF
前言
我们之前使用js库html2canvas + jspdf实现html转PDF、图片,并下载(详情请戳:html页面转PDF、图片操作记录),大致原理是将页面塞到画布里,以图片的方式放到PDF中,生成的文件比较大,文本记录Java使用iText7生成PDF
iText 7是iText强大的PDF工具包的最新版本,用于PDF生成,PDF编程,处理和操作,如数字签名等
官方文档:https://kb.itextpdf.com/home/it7kb/ebooks
简单生成PDF
官方文档:https://kb.itextpdf.com/home/it7kb/ebooks/itext-7-jump-start-tutorial-for-java
根据文档说明,我们引入依赖
<properties>
<!-- 省略其他部分...--> <itext7.version>7.1.7</itext7.version>
</properties> <dependencies>
<!-- 省略其他部分...--> <!-- itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>${itext7.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>io</artifactId>
<version>${itext7.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>${itext7.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>forms</artifactId>
<version>${itext7.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>pdfa</artifactId>
<version>${itext7.version}</version>
</dependency>
</dependencies>
代码
package cn.huanzi.qch.util; import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.annot.PdfLinkAnnotation;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment; import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException; /**
* itextpdf 工具类
* iText 7是iText强大的PDF工具包的最新版本,用于PDF生成,PDF编程,处理和操作,如数字签名等。
* https://kb.itextpdf.com/home/it7kb/ebooks
*/
public class ITextPdfUtil {
//字体,我这里使用系统自带的simhei黑体
private static final String FONT = "C:/Windows/Fonts/simhei.ttf"; //html转pdf
public static void html2pdf(){
String html = ""; //从html文件读取内容
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader("E:\\Java\\html2pdf.html"));){
for (Object o : reader.lines().toArray()) {
stringBuilder.append(o);
}
}catch (Exception e){
e.printStackTrace();
}
html = stringBuilder.toString(); try (PdfWriter writer = new PdfWriter("E:\\Java\\html2pdf.pdf");
PdfDocument pdf = new PdfDocument(writer);
){
//转换器属性设置
ConverterProperties props = new ConverterProperties();
//字体
props.setFontProvider(new FontProvider());
props.getFontProvider().addFont(ITextPdfUtil.FONT);
//为img图片配置基础路径
props.setBaseUri("D:\\XFT User\\Pictures\\"); //HtmlConverter.convertToDocument
Document document = HtmlConverter.convertToDocument(html, pdf, props); //设置文档属性
pdf.getDocumentInfo().setAuthor("huanzi-qch");
pdf.getDocumentInfo().setTitle("IText测试html2pdf");
pdf.getDocumentInfo().setSubject("XXX公司");
pdf.getDocumentInfo().setMoreInfo("1","111");
pdf.getDocumentInfo().setCreator("huanzi");
pdf.getDocumentInfo().setKeywords("IText"); //注册事件监听
pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler()); //设置字体
document.setFont(ITextPdfUtil.getPdfFont()); //页边距
document.setMargins(0, 0, 0, 0); document.close();
System.out.println("操作完成!");
}catch (IOException e){
e.printStackTrace();
System.err.println("操作异常...");
}
} //生成简单PDF
public static void test(){
//语法糖
try (PdfWriter writer = new PdfWriter("E:\\Java\\test.pdf");
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf, PageSize.A4.rotate());
){ //设置文档属性
pdf.getDocumentInfo().setAuthor("huanzi-qch");
pdf.getDocumentInfo().setTitle("IText测试PDF");
pdf.getDocumentInfo().setSubject("XXX公司");
pdf.getDocumentInfo().setMoreInfo("1","111");
pdf.getDocumentInfo().setCreator("huanzi");
pdf.getDocumentInfo().setKeywords("IText"); //注册事件监听
pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler()); //设置字体
document.setFont(ITextPdfUtil.getPdfFont()); //页边距
document.setMargins(20, 20, 20, 20); //简单文字
document.add(new Paragraph("简单文字"));
document.add(new Paragraph("Hello Word!").add(new Tab()).add(new Text("你好!").addStyle(new Style().setFontSize(24)))); //简单图片
document.add(new Paragraph("简单图片"));
document.add(new Image(ImageDataFactory.create("D:\\XFT User\\Pictures\\logo.png"))); //简单表格
document.add(new Paragraph("简单表格"));
Table table = new Table(new float[]{3, 3, 4});
PdfFont font = ITextPdfUtil.getPdfFont();
//标题、内容
process(table, "姓名;年龄;电话号码", font, true);
for (int i = 0; i < 5; i++) {
process(table, "张三"+i+";"+(18+i)+";1500000000"+i, font, false);
}
document.add(table); //超链接
document.add(new Paragraph("超链接"));
PdfLinkAnnotation annotation = new PdfLinkAnnotation(new Rectangle(0, 0));
annotation.setAction(PdfAction.createURI("https://itextpdf.com/"));
Paragraph p = new Paragraph("更多精彩内容,猛戳:").add(new Link("这里", annotation));
document.add(p); //换一页
//document.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); document.close();
System.out.println("操作完成!"); } catch (IOException e) {
e.printStackTrace();
System.err.println("操作异常...");
}
} //获取统一字体
public static PdfFont getPdfFont(){
PdfFont pdfFont = null;
try {
pdfFont = PdfFontFactory.createFont(ITextPdfUtil.FONT, PdfEncodings.IDENTITY_H,true);
} catch (IOException e) {
e.printStackTrace();
}
return pdfFont;
} //设置表格内容
public static void process(Table table, String line, PdfFont font, boolean isHeader) {
String[] split = line.split(";");
for (String s : split) {
Cell cell = new Cell().add(new Paragraph(s).setFont(font));
if (isHeader) {
table.addHeaderCell(cell);
} else {
table.addCell(cell);
}
}
} /**
* 自定义事件监听
*
* 背景颜色
* 页脚页眉
* 文字水印
*
* 也可以分成多个EventHandler
*/
protected static class MyEventHandler implements IEventHandler { @Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = docEvent.getDocument();
PdfPage page = docEvent.getPage();
int pageNumber = pdfDoc.getPageNumber(page);
Rectangle pageSize = page.getPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc); //背景颜色
Color backgroundColor = new DeviceRgb(245, 245, 245);;
pdfCanvas.saveState()
.setFillColor(backgroundColor)
.rectangle(pageSize.getLeft(), pageSize.getBottom(),pageSize.getWidth(), pageSize.getHeight())
.fill().restoreState(); //页脚页眉
PdfFont pdfFont = ITextPdfUtil.getPdfFont();
String header = "我是页眉";
String footer = "第 "+pageNumber+" 页";
pdfCanvas.beginText()
.setFontAndSize(pdfFont, 9)
.moveText((pageSize.getWidth() / 2) - (pdfFont.getWidth(header) / 200), pageSize.getTop() - 20)
.showText(header)
.moveText((pdfFont.getWidth(header) / 200) - (pdfFont.getWidth(footer) / 200), -pageSize.getTop() + 30)
.showText(footer)
.endText(); //文字水印
Canvas canvas = new Canvas(pdfCanvas, pdfDoc, page.getPageSize());
canvas.setFontColor(new DeviceRgb(200, 200, 200));
canvas.setProperty(20, 20);
canvas.setFont(pdfFont);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
canvas.showTextAligned(new Paragraph("我是文字水印").setOpacity(0.8f),(150 + i * 300), (160 + j * 150), pdfDoc.getPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
}
} pdfCanvas.release();
}
} //测试
public static void main(String[] args) {
test(); //html2pdf();
}
}
效果
生成的PDF
文档属性
HTML转PDF
官方文档:https://kb.itextpdf.com/home/it7kb/ebooks/itext-7-converting-html-to-pdf-with-pdfhtml
pdfHTML是iText 7的一个附加组件,需要添加依赖
<properties>
<!-- 省略其他部分...--> <itext7.html2pdf.version>2.1.4</itext7.html2pdf.version>
</properties> <dependencies>
<!-- 省略其他部分...--> <!-- itextpdf html2pdf组件-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>${itext7.html2pdf.version}</version>
</dependency>
</dependencies>
代码
代码同上,仅main测试函数不同!
//测试
public static void main(String[] args) {
//test(); html2pdf();
}
PS:html内容往下拉
效果
html页面
<!DOCTYPE html>
<html>
<head>
<title>简单简历</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="expires" content="0"/> <!-- 自定义样式 -->
<style>
*{
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
} body {
margin: 0;
padding: 0;
} a {
text-decoration: none;
padding: 0;
margin: 5px 0;
color: black;
} a:hover {
color: #5c8dff;
} b{
margin: 0 10px;
} /* 主体 */
.main {
/*margin: 0 auto;*/
/*width: 770px;*/
/*box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);*/
/*border: 1px solid #dad8d8;*/
/*background: #fbfbfb;*/
} /* 1级标题 */
h3.list1 {
color: #409EFF;
border-bottom: 1px solid #409EFF;
padding: 5px;
margin: 50px 0 0 0;
} /* 大模块 */
.block,.block1 {
/*background: #efefef;*/
/*border: 1px solid #dad8d8;*/
margin: 0 0 20px 0;
padding: 0 10px;
}
.block,.block1 p {
text-indent:2em;
} .block:hover {
background: #eeeeee;
}
.block1:hover {
background: #cecece;
} .button-list{
text-align: center;
margin: 20px auto;
padding: 10px;
width: 1024px;
}
</style>
</head>
<body>
<!-- 简历主体 -->
<div id="body" class="main">
<div class="section">
<div class="module">
<h3 class="list1" style="margin: 0;">基本信息</h3>
<div class="block">
<p>XXX<b>/</b>男<b>/</b>25岁</p>
<p>本科<b>/</b>XX学校<b>/</b>XX专业<b>/</b>2014-2018</p>
<p>工龄:X年</p>
<p>手机:XXXXXXXXXX</p>
<p>邮箱:XXXXX@qq.com</p>
<p>GitHub:<a href="https://github.com/huanzi-qch">https://github.com/huanzi-qch</a></p>
<p>博客园:<a href="https://www.cnblogs.com/huanzi-qch">https://www.cnblogs.com/huanzi-qch</a></p>
<br/>
<p>求职岗位:Java开发<b>/</b>目标城市:南宁市<b>/</b>期望薪资:面议</p>
<p>注:已离职,一个月可到岗</p> <img style="position: relative;top: -350px;left: 500px;width: 100px;height: 130px;" src="logo.png"/>
</div>
</div> <div class="module">
<h3 class="list1">技能清单</h3>
<div class="block">
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
<p>熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。</p>
</div>
</div> <div class="module">
<h3 class="list1">工作经历</h3>
<div class="block">
<p>XXX技术有限公司<b>/</b>Java开发工程师<b>/</b>2018.01 - 至今</p>
<p>参与多个项目开发、测试、部署等工作,包括:</p>
<p>1、XXX。</p>
<p>2、XXX。</p>
<p>3、XXX。</p>
</div>
</div> <div class="module">
<h3 class="list1">项目经历</h3>
<div class="block">
<h4 class="list2">项目1</h4>
<div class="block1">
<p>项目名称:XXX(2020-11 —2021-11)</p>
<p>项目介绍:XXXXXXXXXXXXXXX。</p>
<p>技术架构:XXX + XXX + XXX。</p>
<p>职责描述:</p>
<p>1、XXXX。</p>
<p>2、XXXX。</p>
<p>3、XXXX。</p>
<p>4、XXXX。</p>
</div> <h4 class="list2">项目2</h4>
<div class="block1">
<p>项目名称:XXX(2020-11 —2021-11)</p>
<p>项目介绍:XXXXXXXXXXXXXXX。</p>
<p>技术架构:SpringBoot + Vue + Element-UI + ECharts。</p>
<p>职责描述:</p>
<p>1、XXXX。</p>
<p>2、XXXX。</p>
<p>3、XXXX。</p>
<p>4、XXXX。</p>
</div>
</div>
</div> <div class="module">
<h3 class="list1">自我评价</h3>
<div class="block">
<p>1、XXXX;</p>
<p>2、XXXX;</p>
<p>3、XXXX;</p>
</div>
</div>
</div>
</div>
</body>
</html>
生成的PDF
后记
不管是前端生成PDF,还是后端生成PDF,能实现需求就是好技术!
Java使用iText7生成PDF的更多相关文章
- Java iText+FreeMarker生成PDF(HTML转PDF)
1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等.方便用户查看,下载,打印.目前常用的解决方案是,把相关数据信息,生成对应的pdf文件返回给用户. ...
- 【PDF】java使用Itext生成pdf文档--详解
[API接口] 一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/ ...
- java调用wkhtmltopdf生成pdf文件,美观,省事
最近项目需要导出企业风险报告,文件格式为pdf,于是搜了一大批文章都是什么Jasper Report,iText ,flying sauser ,都尝试了一遍,感觉不是我想要的效果, 需要自己调整好多 ...
- Java 使用itext生成pdf以及下载
使用方法: 1.需要两个jar包: iText-5.0.6.jar //必须使用该版本,否则缺少相关的方法 TextAsian.jar //是为了文档中正常显示中文所必须引用的包 TextAsi ...
- java根据模板生成pdf
原文链接:https://www.cnblogs.com/wangpeng00700/p/8418594.html 在网上看了一些Java生成pdf文件的,写的有点乱,有的不支持写入中文字体,有的不支 ...
- Java利用模板生成pdf并导出
1.准备工作 (1)Adobe Acrobat pro软件:用来制作导出模板 (2)itext的jar包 2.开始制作pdf模板 (1)先用word做出模板界面 (2)文件另存为pdf格式文件 (3) ...
- java利用iTextWorker生成pdf
使用itext生成pdf,在linux环境下,中文全部失踪,因为itext要在linux下支持中文字体需要引入itext-asian, 并添加一个字体类. public static class Pd ...
- java使用iText生成pdf表格
转载地址:http://www.open-open.com/code/view/1424011530749 首先需要你自己下载itext相关的jar包并添加引用,或者在maven中添加如下引用配置: ...
- java调用jacob生成pdf,word,excel横向
/* * 传进一个office文件的byte[]以及后缀,生成一个pdf文件的byte[] */ public byte[] jacob_Office2Pdf(byte[] srcFileBytes, ...
随机推荐
- 『Python』matplotlib划分画布的主要函数
1. subplot() 绘制网格区域中几何形状相同的子区布局 函数签名有两种: subplot(numRows, numCols, plotNum) subplot(CRN) 都是整数,意思是将画布 ...
- 通用JS七
instanceof 在原型链上寻找这个属性的定义 match 正则匹配字符串 Symbol() Symbol()函数不能用作构造函数,与new关键字一起使用.这样做是为了避免创建符号包装对象,像使用 ...
- 用Flask 实现文件服务器(包含docker版本)
最近有了公司局域网内共享axure原型的需求,所以用Flask开发了一款文件上传/查看工具,记录一下其中的问题和解决方案 这个工具参照了一位大神的uploads工具 https://zhuanlan. ...
- NOIP 模拟 七十七
100+60+95+30; T4 一个变量打错挂了40.. T1 最大或 考虑从高到低枚举的二进制位,然后和的对应二进制位进行比较.如果两 者相同,那么不论怎么选择,,答案在这个位置上的值一定和在这个 ...
- Netty-FastThreadLocal快在哪里呢?
来源于:https://www.wangdaye.net/archives/n-e-t-t-y-zhi-f-a-s-t-t-h-r-e-a-d-l-o-c-a-l 前言 netty的concurren ...
- [JUC-5]ConcurrentHashMap源码分析JDK8
在学习之前,最好先了解下如下知识: 1.ReentrantLock的实现和原理. 2.Synchronized的实现和原理. 3.硬件对并发支持的CAS操作及JVM中Unsafe对CAS的实现. 4. ...
- Serverless Kubernetes 和 Serverless on Kubernetes 的区别
什么是 Kubernetes? Kubernetes 是一个可移植的.可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化. 什么是 Serverless ? 无服务器是一种云原 ...
- javascript-原生-面向对象
1.javascript面向对象程序设计 概述:javascript不想其他面向对象编程语言那样有类的概念,javascript没有类(构造函数)的概念,只有对象的概念. 2.理解javascript ...
- Coursera Deep Learning笔记 逻辑回归典型的训练过程
Deep Learning 用逻辑回归训练图片的典型步骤. 笔记摘自:https://xienaoban.github.io/posts/59595.html 1. 处理数据 1.1 向量化(Vect ...
- [no code] Scrum Meeting 博客目录
项目 内容 2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 Scrum Meeting博客目录 我们在这个课程的目标是 远程协同工作,采用最新技术 ...