一,什么是itextpdf?

1,itextpdf的用途

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

通过iText可以生成PDF文档,

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

2,官方网站:

  1. https://itextpdf.com/en

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

使用中文字体

插入表格

插入图片时设置图片宽度

浏览器直接显示pdf

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

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

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

二,演示项目的相关信息

1,代码地址:

  1. https://github.com/liuhongdi/exportpdf

2,功能说明:

直接显示pdf

把数据保存成pdf文件

pdf文件下载

3,项目结构:如图:

三,配置文件说明

1,pom.xml

  1. <!--pdf begin-->
  2. <dependency>
  3. <groupId>com.itextpdf</groupId>
  4. <artifactId>itextpdf</artifactId>
  5. <version>5.5.13.1</version>
  6. </dependency>
  7.  
  8. <dependency>
  9. <groupId>com.itextpdf</groupId>
  10. <artifactId>itext-asian</artifactId>
  11. <version>5.2.0</version>
  12. </dependency>
  13. <!--pdf end-->
  14.  
  15. <!--mybatis begin-->
  16. <dependency>
  17. <groupId>org.mybatis.spring.boot</groupId>
  18. <artifactId>mybatis-spring-boot-starter</artifactId>
  19. <version>2.1.3</version>
  20. </dependency>
  21. <!--mybatis end-->
  22.  
  23. <!--mysql begin-->
  24. <dependency>
  25. <groupId>mysql</groupId>
  26. <artifactId>mysql-connector-java</artifactId>
  27. <scope>runtime</scope>
  28. </dependency>
  29. <!--mysql end-->

说明:要引入itextpdf

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

resources/font目录下供访问

3,数据表建表sql

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

四,java代码说明

1,AbstractITextPdfView.java

  1. /**
  2. 新建一个pdfview,主要是为了避免AbstractPdfView中使用的pdf库太旧的问题
  3. AbstractPdfView只支持到 com.lowagie.itext的2.1.7版本,
  4. 版本太旧,文档也缺少
  5. 修改后可以支持itextpdf库的类,
  6. 新增AbstractITextPdfView后此问题完美解决
  7. by liuhongdi
  8. */
  9. public abstract class AbstractITextPdfView extends AbstractView {
  10. public AbstractITextPdfView() {
  11. setContentType("application/pdf");
  12. }
  13.  
  14. @Override
  15. protected boolean generatesDownloadContent() {
  16. return true;
  17. }
  18.  
  19. @Override
  20. protected final void renderMergedOutputModel(Map<String, Object> model,
  21. HttpServletRequest request, HttpServletResponse response)
  22. throws Exception {
  23. // 获得流
  24. ByteArrayOutputStream baos = createTemporaryOutputStream();
  25. Document document = newDocument();
  26. PdfWriter writer = newWriter(document, baos);
  27. prepareWriter(model, writer, request);
  28. buildPdfMetadata(model, document, request);
  29. buildPdfDocument(model, document, writer, request, response);
  30. writeToResponse(response, baos);
  31. }
  32.  
  33. protected Document newDocument() {
  34. return new Document(PageSize.A4);
  35. }
  36.  
  37. protected PdfWriter newWriter(Document document, OutputStream os)
  38. throws DocumentException {
  39. return PdfWriter.getInstance(document, os);
  40. }
  41.  
  42. protected void prepareWriter(Map<String, Object> model, PdfWriter writer,
  43. HttpServletRequest request) throws DocumentException {
  44.  
  45. writer.setViewerPreferences(getViewerPreferences());
  46. }
  47.  
  48. protected int getViewerPreferences() {
  49. return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage;
  50. }
  51.  
  52. protected void buildPdfMetadata(Map<String, Object> model,
  53. Document document, HttpServletRequest request) {
  54. }
  55.  
  56. protected abstract void buildPdfDocument(Map<String, Object> model,
  57. Document document, PdfWriter writer, HttpServletRequest request,
  58. HttpServletResponse response) throws Exception;
  59. }

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

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

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

2, ViewPdfUtil.java

  1. public class ViewPdfUtil extends AbstractITextPdfView {
  2.  
  3. //文件名
  4. private String fileName;
  5. public String getFileName() {
  6. return this.fileName;
  7. }
  8. public void setFileName(String fileName) {
  9. this.fileName = fileName;
  10. }
  11.  
  12. //指定一个类型,方便知道调用哪个类处理
  13. private String pdfType;
  14. public String getPdfType() {
  15. return this.pdfType;
  16. }
  17. public void setPdfType(String pdfType) {
  18. this.pdfType = pdfType;
  19. }
  20.  
  21. //生成pdf的document并显示出来
  22. @Override
  23. protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception {
  24. response.setCharacterEncoding("UTF-8");
  25. response.setContentType("application/pdf");
  26. response.setHeader("Content-Disposition","filename=" + URLEncoder.encode(this.fileName, "UTF-8"));
  27. List<Goods> products = (List<Goods>) model.get("sheet");
  28. if (this.pdfType.equals("goods")) {
  29. PdfTableService pdfTableService = new PdfTableServiceImpl();
  30. //不保存成文件,直接显示,所以不指定保存路径
  31. pdfTableService.createPDF(document, products,"");
  32. }
  33. }
  34. }

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

3,PdfTableServiceImpl.java

  1. @Service
  2. public class PdfTableServiceImpl implements PdfTableService {
  3.  
  4. //创建pdf文件,
  5. // savePath是保存路径,如果是空字串,则直接输出到document
  6. //document:pdf内容
  7. //goods:写入到pdf表格中的数据
  8. @Override
  9. public void createPDF(Document document, List<Goods> goods,String savePath) {
  10. try {
  11. if (!savePath.equals("")) {
  12. PdfWriter.getInstance(document, new FileOutputStream(savePath));
  13. }
  14. document.addTitle("商品库存统计表");
  15. document.addAuthor("老刘");
  16. document.addSubject("2020年商品库存统计");
  17. document.addKeywords("商品库存");
  18. document.open();
  19. Paragraph para = getParagraphText("整个白酒行业从2012年开始,都迅速下滑,销量和利润都是大跌。2014年和2015年,茅台的股价涨得不错,但也没有超过同期的白马股太多,加上利润增速一直没有恢复塑化剂之前的状态,我就一直没有再买入");
  20. document.add(para);
  21. String imagePath = "/data/springboot2/logo.jpg"; // 图片的绝对路径
  22. Image image = Image.getInstance(imagePath); // 取得图片对象
  23. //计算得到目标宽高
  24. File gifFile = new File(imagePath);
  25. int origWidth = 0;
  26. int origHeight = 0;
  27. try {
  28. BufferedImage imageBuffer = ImageIO.read(gifFile);
  29. if (imageBuffer != null) {//如果image=null 表示上传的不是图片格式
  30. origWidth = imageBuffer.getWidth();
  31. origHeight = imageBuffer.getHeight();
  32. }
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36.  
  37. System.out.println("width:"+document.getPageSize().getWidth());
  38. System.out.println("margin:"+document.leftMargin());
  39. //得到新的高度和新的宽度
  40. float newwidth = document.getPageSize().getWidth()-document.leftMargin()-document.rightMargin();
  41. float newHeight = (newwidth*origHeight) / origWidth;
  42.  
  43. image.scaleAbsolute(newwidth, newHeight);
  44.  
  45. document.add(image);
  46.  
  47. PdfPTable table = createTable(goods);
  48. document.add(table);
  49.  
  50. } catch ( IOException e) {
  51. e.printStackTrace();
  52. } catch (DocumentException e) {
  53. e.printStackTrace();
  54. } finally {
  55. if (document.isOpen()) {
  56. document.close();
  57. }
  58. }
  59. }
  60.  
  61. //从text得到可以添加到document的Paragraph
  62. public static Paragraph getParagraphText(String text) {
  63.  
  64. try {
  65. Font font = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
  66. font.setColor(BaseColor.GRAY);
  67.  
  68. Paragraph para = new Paragraph(text,font);
  69. return para;
  70. } catch ( IOException | DocumentException e) {
  71. e.printStackTrace();
  72. return null;
  73. }
  74. }
  75.  
  76. //创建PdfTable
  77. public static PdfPTable createTable(List<Goods> products) throws IOException, DocumentException {
  78. PdfPTable table = new PdfPTable(4);//生成一个4列的表格
  79.  
  80. int widths[] = { 10,40,40,10 };//指定各列的宽度百分比
  81. table.setWidthPercentage(100);
  82. table.setSpacingBefore(10);
  83. table.setWidths(widths);
  84.  
  85. PdfPCell cell;
  86. int size = 20;
  87.  
  88. Font font = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
  89. font.setColor(BaseColor.BLACK);
  90.  
  91. Font font_head = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
  92. font_head.setColor(BaseColor.BLUE);
  93.  
  94. Font font_title = new Font(BaseFont.createFont(new ClassPathResource("/font/FZLTHK.TTF").getPath(),BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
  95. font_title.setColor(BaseColor.GREEN);
  96. font_title.setSize(36);
  97.  
  98. cell = new PdfPCell(new Phrase("商品库存信息表",font_title));
  99. cell.setColspan(4);//设置所占列数
  100. cell.setFixedHeight(50);//设置高度
  101. cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
  102. table.addCell(cell);
  103.  
  104. cell = new PdfPCell(new Phrase("ID",font_head));//商品编号
  105. cell.setFixedHeight(size);
  106. table.addCell(cell);
  107. cell = new PdfPCell(new Phrase("商品名称",font_head));//商品名称
  108. cell.setFixedHeight(size);
  109. table.addCell(cell);
  110. cell = new PdfPCell(new Phrase("描述",font_head));//描述
  111. cell.setFixedHeight(size);
  112. table.addCell(cell);
  113. cell = new PdfPCell(new Phrase("价格",font_head));//商品价格
  114. cell.setFixedHeight(size);
  115. table.addCell(cell);
  116.  
  117. for(int i = 0;i<products.size();i++) {
  118. cell = new PdfPCell(new Phrase(String.valueOf(products.get(i).getGoodsId()),font));//商品编号
  119. cell.setFixedHeight(size);
  120. table.addCell(cell);
  121. cell = new PdfPCell(new Phrase(products.get(i).getGoodsName(),font));//商品名称
  122. cell.setFixedHeight(size);
  123. table.addCell(cell);
  124. cell = new PdfPCell(new Phrase(products.get(i).getSubject(),font));//描述
  125. cell.setFixedHeight(size);
  126. table.addCell(cell);
  127. cell = new PdfPCell(new Phrase(products.get(i).getPrice()+"",font));//商品价格
  128. cell.setFixedHeight(size);
  129. table.addCell(cell);
  130. }
  131. return table;
  132. }
  133.  
  134. }

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

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

4,HomeController.java

  1. @RestController
  2. @RequestMapping("/home")
  3. public class HomeController {
  4.  
  5. @Resource
  6. private GoodsMapper goodsMapper;
  7.  
  8. @Resource
  9. PdfTableService pdfTableService;
  10.  
  11. //把数据保存到pdf文件
  12. @GetMapping("/savepdf")
  13. public String savepdf() {
  14. List<Goods> goodsList = goodsMapper.selectAllGoods();
  15. String savePath = "/data/springboot2/goodslist.pdf";
  16. pdfTableService.createPDF(new Document(PageSize.A4), goodsList,savePath);
  17. return "pdf saveed";
  18. }
  19.  
  20. //从浏览器直接显示pdf
  21. @GetMapping("/viewpdf")
  22. public ModelAndView viewpdf() {
  23. List<Goods> goodsList = goodsMapper.selectAllGoods();
  24. Map<String, Object> model = new HashMap<>();
  25. model.put("sheet", goodsList);
  26. ViewPdfUtil viewPdf = new ViewPdfUtil();
  27. viewPdf.setFileName("测试.pdf");
  28. viewPdf.setPdfType("goods");
  29. return new ModelAndView(viewPdf, model);
  30. }
  31.  
  32. //下载pdf文件
  33. @GetMapping("/downpdf")
  34. public void downpdf() {
  35. String filepath = "/data/springboot2/goodslist.pdf";
  36. PdfUtil.downPdfFile(filepath);
  37. }
  38. }

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

五,效果测试

1,直接显示:

访问:

  1. http://127.0.0.1:8080/home/viewpdf

如图:

2,直接保存成pdf文件:

访问:

  1. http://127.0.0.1:8080/home/savepdf

效果如图:

3,下载pdf文件:

访问:

  1. http://127.0.0.1:8080/home/downpdf

六,查看spring boot的版本:

  1. . ____ _ __ _ _
  2. /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
  3. ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
  4. \\/ ___)| |_)| | | | | || (_| | ) ) ) )
  5. ' |____| .__|_| |_|_| |_\__, | / / / /
  6. =========|_|==============|___/=/_/_/_/
  7. :: 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. 安卓自动化测试工具Monkey简单使用

    一.首先安装adb 地址:http://www.downza.cn/soft/219906.html安装到D盘下,安装的过程中自己注意下不要安装上全家桶.找到这个压缩包:解压到当前文件夹: 二.将ad ...

  2. 漏洞扫描工具acunetix破解安装步骤

    Acunetix 12破解版安装教程 下载地址: 链接:https://pan.baidu.com/s/1jsKkrhOcx_O7ib7FQ6pidw 提取码:pwdj 1.下载软件压缩包文件,首先点 ...

  3. [LeetCode]96. 不同的二叉搜索树(DP,卡特兰数)

    题目 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ ...

  4. [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)

    695. 岛屿的最大面积 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被 ...

  5. json出现引用 "$ref": "$.conpolice[2]"

    1. 出现这个问题一般是因为代码循环引用出现的问题,可以改变逻辑,也可以直接加上下面加粗的代码 JSONObject jsonObject = new JSONObject(); jsonObject ...

  6. Druid实现数据库连接用户密码加密

    使用ConfigFilter ConfigFilter的作用包括: 从配置文件中读取配置 从远程http文件中读取配置 为数据库密码提供加密功能 1 配置ConfigFilter 1.1 配置文件从本 ...

  7. dubbo学习(四)配置dubbo 注解方式配置

    provider(生产者) service注解暴露服务 /** * 用户管理实现类 */ @Service //用的dubbo的注解,表明这是一个分布式服务 @Component //注册为sprin ...

  8. Java环境变量配置 新手必备

    第一步:安装JDK,无脑下一步 建议修改安装路径 这里以jdk1.7为例子(之前帮机房安装软件,五六十台电脑都要用1.7); 2.安装完了之后右击此电脑,打开属性 打开系统高级设置 打开环境变量 这里 ...

  9. Salesforce LWC学习(二十六) 简单知识总结篇三

    首先本篇感谢长源edward老哥的大力帮助. 背景:我们在前端开发的时候,经常会用到输入框,并且对这个输入框设置 required或者其他的验证,当不满足条件时使用自定义的UI或者使用标准的 inpu ...

  10. Linux Wait Queue 等待队列

    一.引言 linux 内核的等待队列和进程调度息息相关,进程在某些情况下必须等待某些事件的发生,例如:等待一个磁盘操作的终止,等待释放系统资源,或等待指定的时间间隔. 等待队列实现了在事件上的条件等待 ...