一,什么是itextpdf?

1,itextpdf的用途

itextpdf是用来生成PDF文档的一个java类库,

通过iText可以生成PDF文档,

还可以把XML/Html文件转化为PDF文件

2,官方网站:

https://itextpdf.com/en

3,itextpdf使用中的几个问题:

使用中文字体

插入表格

插入图片时设置图片宽度

浏览器直接显示pdf

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,代码地址:

https://github.com/liuhongdi/exportpdf

2,功能说明:

直接显示pdf

把数据保存成pdf文件

pdf文件下载

3,项目结构:如图:

三,配置文件说明

1,pom.xml

        <!--pdf begin-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
</dependency> <dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!--pdf end--> <!--mybatis begin-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--mybatis end--> <!--mysql begin-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mysql end-->

说明:要引入itextpdf

2,把自己要使用的字体文件,复制到

resources/font目录下供访问

3,数据表建表sql

CREATE TABLE `goods` (
`goodsId` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`goodsName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'name',
`subject` varchar(200) NOT NULL DEFAULT '' COMMENT '标题',
`price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
`stock` int(11) NOT NULL DEFAULT '0' COMMENT 'stock',
PRIMARY KEY (`goodsId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表'

四,java代码说明

1,AbstractITextPdfView.java

/**
新建一个pdfview,主要是为了避免AbstractPdfView中使用的pdf库太旧的问题
AbstractPdfView只支持到 com.lowagie.itext的2.1.7版本,
版本太旧,文档也缺少
修改后可以支持itextpdf库的类,
新增AbstractITextPdfView后此问题完美解决
by liuhongdi
*/
public abstract class AbstractITextPdfView extends AbstractView {
public AbstractITextPdfView() {
setContentType("application/pdf");
} @Override
protected boolean generatesDownloadContent() {
return true;
} @Override
protected final void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 获得流
ByteArrayOutputStream baos = createTemporaryOutputStream();
Document document = newDocument();
PdfWriter writer = newWriter(document, baos);
prepareWriter(model, writer, request);
buildPdfMetadata(model, document, request);
buildPdfDocument(model, document, writer, request, response);
writeToResponse(response, baos);
} protected Document newDocument() {
return new Document(PageSize.A4);
} protected PdfWriter newWriter(Document document, OutputStream os)
throws DocumentException {
return PdfWriter.getInstance(document, os);
} protected void prepareWriter(Map<String, Object> model, PdfWriter writer,
HttpServletRequest request) throws DocumentException { writer.setViewerPreferences(getViewerPreferences());
} protected int getViewerPreferences() {
return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage;
} protected void buildPdfMetadata(Map<String, Object> model,
Document document, HttpServletRequest request) {
} protected abstract void buildPdfDocument(Map<String, Object> model,
Document document, PdfWriter writer, HttpServletRequest request,
HttpServletResponse response) throws Exception;
}

说明:如果在浏览器的页面上直接显示pdf,而不是下载文件后再打开,

则需要使用AbstractPdfView,但spring boot默认支持的itext库代码太旧,

注释中已做了说明,所以我们另外自己定义一个

2, ViewPdfUtil.java

public class ViewPdfUtil extends AbstractITextPdfView {

    //文件名
private String fileName;
public String getFileName() {
return this.fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
} //指定一个类型,方便知道调用哪个类处理
private String pdfType;
public String getPdfType() {
return this.pdfType;
}
public void setPdfType(String pdfType) {
this.pdfType = pdfType;
} //生成pdf的document并显示出来
@Override
protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","filename=" + URLEncoder.encode(this.fileName, "UTF-8"));
List<Goods> products = (List<Goods>) model.get("sheet");
if (this.pdfType.equals("goods")) {
PdfTableService pdfTableService = new PdfTableServiceImpl();
//不保存成文件,直接显示,所以不指定保存路径
pdfTableService.createPDF(document, products,"");
}
}
}

说明:主要是实现buildPdfDocument方法,供ModelAndView调用时直接显示到浏览器页面

3,PdfTableServiceImpl.java

@Service
public class PdfTableServiceImpl implements PdfTableService { //创建pdf文件,
// savePath是保存路径,如果是空字串,则直接输出到document
//document:pdf内容
//goods:写入到pdf表格中的数据
@Override
public void createPDF(Document document, List<Goods> goods,String savePath) {
try {
if (!savePath.equals("")) {
PdfWriter.getInstance(document, new FileOutputStream(savePath));
}
document.addTitle("商品库存统计表");
document.addAuthor("老刘");
document.addSubject("2020年商品库存统计");
document.addKeywords("商品库存");
document.open();
Paragraph para = getParagraphText("整个白酒行业从2012年开始,都迅速下滑,销量和利润都是大跌。2014年和2015年,茅台的股价涨得不错,但也没有超过同期的白马股太多,加上利润增速一直没有恢复塑化剂之前的状态,我就一直没有再买入");
document.add(para);
String imagePath = "/data/springboot2/logo.jpg"; // 图片的绝对路径
Image image = Image.getInstance(imagePath); // 取得图片对象
//计算得到目标宽高
File gifFile = new File(imagePath);
int origWidth = 0;
int origHeight = 0;
try {
BufferedImage imageBuffer = ImageIO.read(gifFile);
if (imageBuffer != null) {//如果image=null 表示上传的不是图片格式
origWidth = imageBuffer.getWidth();
origHeight = imageBuffer.getHeight();
}
} catch (IOException e) {
e.printStackTrace();
} System.out.println("width:"+document.getPageSize().getWidth());
System.out.println("margin:"+document.leftMargin());
//得到新的高度和新的宽度
float newwidth = document.getPageSize().getWidth()-document.leftMargin()-document.rightMargin();
float newHeight = (newwidth*origHeight) / origWidth; image.scaleAbsolute(newwidth, newHeight); document.add(image); PdfPTable table = createTable(goods);
document.add(table); } catch ( IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} finally {
if (document.isOpen()) {
document.close();
}
}
} //从text得到可以添加到document的Paragraph
public static Paragraph getParagraphText(String text) { try {
Font font = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
font.setColor(BaseColor.GRAY); Paragraph para = new Paragraph(text,font);
return para;
} catch ( IOException | DocumentException e) {
e.printStackTrace();
return null;
}
} //创建PdfTable
public static PdfPTable createTable(List<Goods> products) throws IOException, DocumentException {
PdfPTable table = new PdfPTable(4);//生成一个4列的表格 int widths[] = { 10,40,40,10 };//指定各列的宽度百分比
table.setWidthPercentage(100);
table.setSpacingBefore(10);
table.setWidths(widths); PdfPCell cell;
int size = 20; Font font = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
font.setColor(BaseColor.BLACK); Font font_head = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
font_head.setColor(BaseColor.BLUE); Font font_title = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
font_title.setColor(BaseColor.GREEN);
font_title.setSize(36); cell = new PdfPCell(new Phrase("商品库存信息表",font_title));
cell.setColspan(4);//设置所占列数
cell.setFixedHeight(50);//设置高度
cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
table.addCell(cell); cell = new PdfPCell(new Phrase("ID",font_head));//商品编号
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase("商品名称",font_head));//商品名称
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase("描述",font_head));//描述
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase("价格",font_head));//商品价格
cell.setFixedHeight(size);
table.addCell(cell); for(int i = 0;i<products.size();i++) {
cell = new PdfPCell(new Phrase(String.valueOf(products.get(i).getGoodsId()),font));//商品编号
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase(products.get(i).getGoodsName(),font));//商品名称
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase(products.get(i).getSubject(),font));//描述
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase(products.get(i).getPrice()+"",font));//商品价格
cell.setFixedHeight(size);
table.addCell(cell);
}
return table;
} }

用途:把数据添加到pdf的 document,注意对中文字体的引用

另外注意插入图片时得到默认宽度的计算,需要减掉两侧的margin

4,HomeController.java

@RestController
@RequestMapping("/home")
public class HomeController { @Resource
private GoodsMapper goodsMapper; @Resource
PdfTableService pdfTableService; //把数据保存到pdf文件
@GetMapping("/savepdf")
public String savepdf() {
List<Goods> goodsList = goodsMapper.selectAllGoods();
String savePath = "/data/springboot2/goodslist.pdf";
pdfTableService.createPDF(new Document(PageSize.A4), goodsList,savePath);
return "pdf saveed";
} //从浏览器直接显示pdf
@GetMapping("/viewpdf")
public ModelAndView viewpdf() {
List<Goods> goodsList = goodsMapper.selectAllGoods();
Map<String, Object> model = new HashMap<>();
model.put("sheet", goodsList);
ViewPdfUtil viewPdf = new ViewPdfUtil();
viewPdf.setFileName("测试.pdf");
viewPdf.setPdfType("goods");
return new ModelAndView(viewPdf, model);
} //下载pdf文件
@GetMapping("/downpdf")
public void downpdf() {
String filepath = "/data/springboot2/goodslist.pdf";
PdfUtil.downPdfFile(filepath);
}
}

三个功能:直接显示,保存成文件,下载

五,效果测试

1,直接显示:

访问:

http://127.0.0.1:8080/home/viewpdf

如图:

2,直接保存成pdf文件:

访问:

http://127.0.0.1:8080/home/savepdf

效果如图:

3,下载pdf文件:

访问:

http://127.0.0.1:8080/home/downpdf

六,查看spring boot的版本:

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.2.RELEASE)

spring boot:用itextpdf处理pdf表格文件(spring boot 2.3.2)的更多相关文章

  1. spring boot:使用poi导出excel电子表格文件(spring boot 2.3.1)

    一,什么是poi? 1,poi poi是用来兼容微软文档格式的java api, 它是apache的顶级项目之一, 也是我们在生产环境中导出excel时使用最多的库 2,poi官方网站: http:/ ...

  2. Spring实战(第4版).pdf - 百度云资源

    http://www.supan.vip/spring%E5%AE%9E%E6%88%98 Spring实战(第4版).pdf 关于本书 Spring框架是以简化Java EE应用程序的开发为目标而创 ...

  3. 导出文本、表格、图像到PDF格式文件中(学习整理)

    1.测试例子: 需要导入的外部jar包: 相关API http://www.coderanch.com/how-to/javadoc/itext-2.1.7/com/lowagie/text/pack ...

  4. Spring boot 国际化自动加载资源文件问题

    Spring boot 国际化自动加载资源文件问题 最近在做基于Spring boot配置的项目.中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义 ...

  5. [转载]Java集成PageOffice在线打开编辑word文件 - Spring Boot

    开发环境:JDK1.8.Eclipse.Sping Boot + Thymeleaf框架. 一. 构建Sping Boot + Thymeleaf框架的项目(不再详述): 1. 新建一个maven p ...

  6. [原创]Java集成PageOffice在线打开编辑word文件 - Spring Boot

    开发环境:JDK1.8.Eclipse.Sping Boot + Thymeleaf框架. 一. 构建Sping Boot + Thymeleaf框架的项目(不再详述): 1. 新建一个maven p ...

  7. 【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑

    编写Java Spring Boot应用,通过配置logging.path路径把日志输出在指定的文件夹中. 第一步:通过VS Code创建一个空的Spring Boot项目 第二步:在applicat ...

  8. MVC 生成PDf表格并插入图片

    最近做的项目中有一个功能,将最终的个人信息生成PDF表格,并插入图片.对于没接触过的程序员来说回一片茫然,网上有多种生成PDf的方法,我给大家介绍一下我认为比较简单,好操作的一种. iTextShar ...

  9. 朱晔和你聊Spring系列S1E7:简单好用的Spring Boot Actuator

    阅读PDF版本 本文会来看一下Spring Boot Actuator提供给我们的监控端点Endpoint.健康检查Health和打点指标Metrics等所谓的Production-ready(生产环 ...

随机推荐

  1. python基础:日志模块logging,nnlog

    python里面用来打印日志的模块,就是logging模块,logging模块可以在控制台打印日志,也可以写入文件中.也可以两个操作都执行 1.控制台输入 import logging#导入模块 lo ...

  2. Java 合并、拆分PPT幻灯片

    序 在日常使用PPT时,为了便于操作和管理文档,时常会遇到需要将PPT幻灯片进行合并或拆分的情况.本文将通过Java程序来演示如何进行上述操作. 示例要点: 1. 合并PPT幻灯片 1.1 将第一个P ...

  3. 反序列化之PHP

    反序列化漏洞 #PHP反序列化 原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果.在反序列化的过程中自动触发了某些魔术方法. ...

  4. 详解usbmon抓取的log各字段的含义

    详解 usbmon 抓取的 log 各字段的含义 在上篇文章中,我们已经介绍了如何在 linux 下使用 usbmon 抓取 usb 总线上数据的方法.(https://www.cnblogs.com ...

  5. 关于java基础_方法的学习

    方法: 方法就是把一堆需要反复执行的代码封装起来,如果项目需要调用这段代码时,直接调用方法名即可 方法相当于榨汁机, 材料:水果 产出物:果汁 参数(材料):进入方法的数据 返回值(产出物):就是方法 ...

  6. Docker实战(5)升级Docker版本后的报错

    出现情况:因我升级了Centos内核后docker服务无法开启,所做重装处理但还是无效,最终将docker服务做了升级,升级步骤我会放置下面,但在启动老版本容器又出现Error response fr ...

  7. 用华为HMS ML kit人体骨骼识别技术,Android快速实现人体姿势动作抓拍&nbsp;

      你有没有过这种体验,拍照时对着镜头,脑子一片空白.表情僵硬.手和脚无处安放,最后拍出来的照片很是奇怪.拍照软件中的固定姿势抓拍功能可以帮助你:选择一个你想要的姿势模板,当你摆出同款姿势时,软件会进 ...

  8. zookeeper(5) 客户端

    zookeeper客户端主要负责与用户进行交互,将命令发送到服务器,接收服务器的响应,反馈给用户.主要分为一下三层: 用户命令处理层 用户命令处理层的功能是读取用户输入的命令,解析用户命令和输入参数, ...

  9. 刷题[HFCTF2020]EasyLogin

    前置知识 node.js koa框架常用目录,文件 js弱类型语言,空数组与整数1比较时,返回turue jwt令牌 博客讲解: 关于jwt的讲解: http://www.ruanyifeng.com ...

  10. 有关Kafka的那些事

    Kafka基本概念 Producer: 消息和数据的生产者,向kafka的一个topic发布消息的进程.代码.服务. Consumer:消息和数据的消费者,订阅数据并且处理器发布的消息的进程.代码.服 ...