spring boot:用itextpdf处理pdf表格文件(spring boot 2.3.2)
一,什么是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)的更多相关文章
- spring boot:使用poi导出excel电子表格文件(spring boot 2.3.1)
一,什么是poi? 1,poi poi是用来兼容微软文档格式的java api, 它是apache的顶级项目之一, 也是我们在生产环境中导出excel时使用最多的库 2,poi官方网站: http:/ ...
- Spring实战(第4版).pdf - 百度云资源
http://www.supan.vip/spring%E5%AE%9E%E6%88%98 Spring实战(第4版).pdf 关于本书 Spring框架是以简化Java EE应用程序的开发为目标而创 ...
- 导出文本、表格、图像到PDF格式文件中(学习整理)
1.测试例子: 需要导入的外部jar包: 相关API http://www.coderanch.com/how-to/javadoc/itext-2.1.7/com/lowagie/text/pack ...
- Spring boot 国际化自动加载资源文件问题
Spring boot 国际化自动加载资源文件问题 最近在做基于Spring boot配置的项目.中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义 ...
- [转载]Java集成PageOffice在线打开编辑word文件 - Spring Boot
开发环境:JDK1.8.Eclipse.Sping Boot + Thymeleaf框架. 一. 构建Sping Boot + Thymeleaf框架的项目(不再详述): 1. 新建一个maven p ...
- [原创]Java集成PageOffice在线打开编辑word文件 - Spring Boot
开发环境:JDK1.8.Eclipse.Sping Boot + Thymeleaf框架. 一. 构建Sping Boot + Thymeleaf框架的项目(不再详述): 1. 新建一个maven p ...
- 【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
编写Java Spring Boot应用,通过配置logging.path路径把日志输出在指定的文件夹中. 第一步:通过VS Code创建一个空的Spring Boot项目 第二步:在applicat ...
- MVC 生成PDf表格并插入图片
最近做的项目中有一个功能,将最终的个人信息生成PDF表格,并插入图片.对于没接触过的程序员来说回一片茫然,网上有多种生成PDf的方法,我给大家介绍一下我认为比较简单,好操作的一种. iTextShar ...
- 朱晔和你聊Spring系列S1E7:简单好用的Spring Boot Actuator
阅读PDF版本 本文会来看一下Spring Boot Actuator提供给我们的监控端点Endpoint.健康检查Health和打点指标Metrics等所谓的Production-ready(生产环 ...
随机推荐
- 安卓自动化测试工具Monkey简单使用
一.首先安装adb 地址:http://www.downza.cn/soft/219906.html安装到D盘下,安装的过程中自己注意下不要安装上全家桶.找到这个压缩包:解压到当前文件夹: 二.将ad ...
- 漏洞扫描工具acunetix破解安装步骤
Acunetix 12破解版安装教程 下载地址: 链接:https://pan.baidu.com/s/1jsKkrhOcx_O7ib7FQ6pidw 提取码:pwdj 1.下载软件压缩包文件,首先点 ...
- [LeetCode]96. 不同的二叉搜索树(DP,卡特兰数)
题目 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ ...
- [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)
695. 岛屿的最大面积 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被 ...
- json出现引用 "$ref": "$.conpolice[2]"
1. 出现这个问题一般是因为代码循环引用出现的问题,可以改变逻辑,也可以直接加上下面加粗的代码 JSONObject jsonObject = new JSONObject(); jsonObject ...
- Druid实现数据库连接用户密码加密
使用ConfigFilter ConfigFilter的作用包括: 从配置文件中读取配置 从远程http文件中读取配置 为数据库密码提供加密功能 1 配置ConfigFilter 1.1 配置文件从本 ...
- dubbo学习(四)配置dubbo 注解方式配置
provider(生产者) service注解暴露服务 /** * 用户管理实现类 */ @Service //用的dubbo的注解,表明这是一个分布式服务 @Component //注册为sprin ...
- Java环境变量配置 新手必备
第一步:安装JDK,无脑下一步 建议修改安装路径 这里以jdk1.7为例子(之前帮机房安装软件,五六十台电脑都要用1.7); 2.安装完了之后右击此电脑,打开属性 打开系统高级设置 打开环境变量 这里 ...
- Salesforce LWC学习(二十六) 简单知识总结篇三
首先本篇感谢长源edward老哥的大力帮助. 背景:我们在前端开发的时候,经常会用到输入框,并且对这个输入框设置 required或者其他的验证,当不满足条件时使用自定义的UI或者使用标准的 inpu ...
- Linux Wait Queue 等待队列
一.引言 linux 内核的等待队列和进程调度息息相关,进程在某些情况下必须等待某些事件的发生,例如:等待一个磁盘操作的终止,等待释放系统资源,或等待指定的时间间隔. 等待队列实现了在事件上的条件等待 ...