【PDF】使用 SpringBoot 导出 PDF 文件

太过爱你忘了你带给我的痛 2023-10-02 14:13 114阅读 0赞

使用 iText 导出 pdf 表格

iText 是一种生成 PDF 报表的 Java 组件,先把 jar 包下下来,maven 依赖如下:

  1. <dependency>
  2. <groupId>com.itextpdf</groupId>
  3. <artifactId>itextpdf</artifactId>
  4. <version>5.0.6</version>
  5. </dependency>

1. Hello World

接下来咱们就来搞一个 PDF 入门案例吧。

新建一个 SpringBoot 项目:
在这里插入图片描述
导入 POM 依赖

Controller:

  1. @RestController
  2. @RequestMapping("/pdf")
  3. public class PdfContoller {
  4. @Autowired
  5. private PdfService pdfService;
  6. // 导出pdf
  7. @PostMapping("/exportPdf")
  8. public void exportPdf() {
  9. pdfService.exportPdf();
  10. }
  11. }

Service:

  1. public interface PdfService {
  2. void exportPdf();
  3. }

ServiceImpl:

  1. @Service
  2. @Slf4j
  3. public class PdfServiceImpl implements PdfService {
  4. @Override
  5. public void exportPdf() {
  6. log.info("进入到方法exportPdf()");
  7. String fileName = "test.pdf";
  8. try {
  9. PdfUtil.createPdf(fileName);
  10. } catch (DocumentException e) {
  11. log.error("【DocumentException】报错信息为{}", e.getMessage());
  12. } catch (FileNotFoundException e) {
  13. log.error("【FileNotFoundException】报错信息为{}", e.getMessage());
  14. }
  15. log.info("生成pdf文件完毕");
  16. }
  17. }

util:

  1. public class PdfUtil {
  2. // 生成pdf
  3. public static void createPdf(String fileName) throws DocumentException, FileNotFoundException {
  4. // 1.创建一个文档实例 设置文档纸张为A4
  5. Document document = new Document(PageSize.A4);
  6. // 2.创建PdfWriter对象,设置pdf生成路径
  7. PdfWriter.getInstance(document, new FileOutputStream(fileName));
  8. // 3.打开文档进行我们需要的操作
  9. document.open();
  10. document.add(new Paragraph("Hello World"));
  11. // 4.关闭文档
  12. document.close();
  13. }
  14. }

调用接口:

  1. http://localhost:8080/pdf/exportPdf

会在当前工程下面生成一个 test.pdf 文件:
在这里插入图片描述
好了,iText 入门就到这了。

2. 生成一个表格的 PDF 文件

在工作中,用到比较多的就是导出 PDF 表格了,这里要用到一个很关键的类com.itextpdf.text.pdf.PDFPTable

生成一个如下的表格:

在这里插入图片描述

这是一个 2 列 5 行的表格。其中,单元格 five 占据 2 列;单元格 six 占据 两行。好了,接下来看看如何实现吧。

PdfServiceImpl:

  1. @Override
  2. public void exportPdf2() {
  3. String fileName = "test2.pdf";
  4. try {
  5. // 重点方法
  6. PdfUtil.createPdf2(fileName);
  7. } catch (DocumentException e) {
  8. e.printStackTrace();
  9. } catch (FileNotFoundException e) {
  10. e.printStackTrace();
  11. }
  12. }

PdfUtil:

  1. package com.zzc.hardcore.util;
  2. import com.itextpdf.text.*;
  3. import com.itextpdf.text.pdf.BaseFont;
  4. import com.itextpdf.text.pdf.PdfPCell;
  5. import com.itextpdf.text.pdf.PdfPTable;
  6. import com.itextpdf.text.pdf.PdfWriter;
  7. import java.io.FileNotFoundException;
  8. import java.io.FileOutputStream;
  9. /**
  10. * @author zzc
  11. * @description:PDF工具类
  12. * @create 2021-11-07 16:10
  13. */
  14. public class PdfUtil {
  15. // 字体路径
  16. public static String fontPath = "C:/Users/zzc/Desktop/msyh.ttc,0";
  17. // 字体
  18. public static BaseFont baseFont = null;
  19. static {
  20. try {
  21. baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. // 生成pdf文件
  27. public static void createPdf2(String fileName) throws DocumentException, FileNotFoundException {
  28. // 1.创建一个文档实例 设置文档纸张为A4
  29. Document document = new Document(PageSize.A4);
  30. // 2.创建PdfWriter对象,设置pdf生成路径
  31. PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream(fileName));
  32. // 3.打开文档进行我们需要的操作
  33. document.open();
  34. Paragraph title = new Paragraph("Hello World");
  35. Font font = new Font(baseFont, 8);
  36. title.setFont(font);
  37. title.setAlignment(Element.ALIGN_CENTER);
  38. document.add(title);
  39. // 4.获取表格信息
  40. PdfPTable table = createTable();
  41. document.add(table);
  42. // 5.关闭文档
  43. document.close();
  44. }
  45. // 获取表格信息
  46. public static PdfPTable createTable() throws DocumentException{
  47. // 1.生成表格
  48. PdfPTable table = doCreateTable();
  49. // 2.生成单元格
  50. PdfPCell cell11 = createSpecialCell("one");
  51. table.addCell(cell11);
  52. PdfPCell cell12 = createCell("two");
  53. // 不要边框
  54. cell12.setBorder(0);
  55. table.addCell(cell12);
  56. PdfPCell cell21 = createCell("three");
  57. cell21.setHorizontalAlignment(Element.ALIGN_CENTER);
  58. cell21.setVerticalAlignment(Element.ALIGN_MIDDLE);
  59. table.addCell(cell21);
  60. PdfPCell cell22 = createCell("four");
  61. table.addCell(cell22);
  62. PdfPCell cell3 = createCell("five");
  63. cell3.setColspan(2);
  64. table.addCell(cell3);
  65. PdfPCell cell41 = createCell("six");
  66. cell41.setMinimumHeight(2 * 20);
  67. cell41.setRowspan(2);
  68. table.addCell(cell41);
  69. PdfPCell cell42 = createCell("seven");
  70. table.addCell(cell42);
  71. PdfPCell cell43 = createCell("eight");
  72. table.addCell(cell43);
  73. return table;
  74. }
  75. // 生成表格
  76. public static PdfPTable doCreateTable() throws DocumentException {
  77. // 列数
  78. int columns = 2;
  79. // 1.生成一个两列的表格
  80. PdfPTable table = new PdfPTable(columns);
  81. // 表格占比100%
  82. table.setWidthPercentage(100);
  83. table.setSpacingBefore(20f);
  84. table.setSpacingAfter(20f);
  85. // 2.每一个列宽
  86. float[] columnWidths = {
  87. 2f, 5f};
  88. table.setWidths(columnWidths);
  89. return table;
  90. }
  91. // 生成单元格
  92. public static PdfPCell createCell(String cellContent) {
  93. Phrase phrase = new Phrase(cellContent);
  94. phrase.setFont(new Font(baseFont, 5));
  95. PdfPCell cell = new PdfPCell(phrase);
  96. return cell;
  97. }
  98. // 生成一个有特性的单元格
  99. public static PdfPCell createSpecialCell(String cellContent) {
  100. PdfPCell cell = createCell(cellContent);
  101. // 边框:蓝色
  102. cell.setBorderColor(BaseColor.BLUE);
  103. // 内边距:10
  104. cell.setPaddingLeft(10);
  105. // 水平居中
  106. cell.setHorizontalAlignment(Element.ALIGN_CENTER);
  107. return cell;
  108. }
  109. }

说明:

  1. 要想显示中文字体,必须引入字体文件,我这里免费提供一个 pdf字体下载
  2. PDF 中的 API 使用:Document、PdfPTable、PdfPCell

Document

  1. Document document = new Document(PageSize.A4);
  2. PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream(fileName));
  3. document.open();
  4. // document.add()
  5. document.close();

pdf 文件中需要什么内容,直接调用 document.add() 进行添加

PdfPTable

  1. table.setWidthPercentage(100);
  2. table.setSpacingBefore(20f);
  3. table.setSpacingAfter(20f);
  4. // 每一个列宽
  5. table.setWidths(columnWidths);

表格中添加单元格,必须得调用:table.addCell();

PdfPCell

  1. // 添加边框颜色
  2. cell.setBorderColor(BaseColor.BLUE);
  3. // 不要边框
  4. cell12.setBorder(0);
  5. // 单元格内边距
  6. cell.setPaddingLeft(10);
  7. // 单元格内容水平居中
  8. cell.setHorizontalAlignment(Element.ALIGN_CENTER);
  9. // 单元格内容垂直居中
  10. cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  11. // 设置最小高度
  12. cell.setMinimumHeight();
  13. // 合并列
  14. cell.setColspan(2);
  15. // 合并行
  16. cell.setRowspan(2);

【注意】:每一行的长度要和初始化表格的长度相等,即要把整行给占满,否则后面的都不会打印出来

在这里插入图片描述
如上图,大致意思是:如果你是一个 5 * 2 的单元格,并且,每一个单元格默认宽度为 1,那么,每一行的单元格必须要有 2 个,这样,才会默认切换到下一行去。

3. 下载生成的 PDF 文件

前面的东西都是放到 java 项目中去跑的,没有太多实际用处,在 web 项目中用到才算真正的应用。接下来咱们就通过浏览器去下载生成的 pdf 文件。

咱们下载前面生成的 pdf 文件:

PdfContoller:

  1. @PostMapping("/exportPdf2")
  2. public void exportPdf2(HttpServletResponse response) {
  3. pdfService.exportPdf2(response);
  4. }

PdfServiceImpl:

  1. @Override
  2. public void exportPdf2(HttpServletResponse response) {
  3. String fileName = "test2.pdf";
  4. try {
  5. // 1.生成pdf文件
  6. PdfUtil.createPdf2(fileName);
  7. // 2.下载pdf文件
  8. downLoadFile(fileName, response);
  9. // 3.删除临时生成的pdf文件
  10. deleteFile(new File(fileName));
  11. } catch (DocumentException e) {
  12. e.printStackTrace();
  13. } catch (FileNotFoundException e) {
  14. e.printStackTrace();
  15. }
  16. }

下载 pdf 文件:

  1. public boolean downLoadFile(String fileName, HttpServletResponse response) {
  2. boolean flag = false;
  3. log.info("【下载文件】文件名为:{}", fileName);
  4. File file = new File(fileName);
  5. if (!file.exists()) {
  6. log.error("【下载文件】文件{}不存在", fileName);
  7. return flag;
  8. }
  9. // 法一:
  10. /*try(InputStream in = new BufferedInputStream(new FileInputStream(fileName))){
  11. byte[] buffer = new byte[in.available()];
  12. int length = 0;
  13. while ((length = in.read(buffer)) > 0) {
  14. response.reset();
  15. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
  16. response.addHeader("Content-Length", "" + file.length());
  17. response.setContentType("application/pdf");
  18. OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
  19. toClient.write(buffer);
  20. toClient.flush();
  21. toClient.close();
  22. }
  23. flag = true;*/
  24. // 法二:
  25. try {
  26. InputStream in = new FileInputStream(fileName);
  27. OutputStream outputStream = response.getOutputStream();
  28. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
  29. response.addHeader("Content-Length", "" + file.length());
  30. response.setContentType("application/pdf");
  31. IOUtils.copy(in, outputStream);
  32. flag = true;
  33. in.close();
  34. outputStream.close();
  35. } catch (Exception e) {
  36. log.error("【下载文件】下载文件失败,失败信息为{}", e.getMessage());
  37. return flag;
  38. }
  39. return flag;
  40. }

删除临时生成的pdf文件:

  1. // 递归删除目录下的所有文件及子目录下所有文件
  2. public static boolean deleteFile(File file) {
  3. if (!file.exists()) {
  4. return false;
  5. }
  6. if (file.isDirectory()) {
  7. String[] children = file.list();
  8. //递归删除目录中的子目录下
  9. for (int i=0; i<children.length; i++) {
  10. boolean success = deleteFile(new File(file, children[i]));
  11. if (!success) {
  12. return false;
  13. }
  14. }
  15. }
  16. // 目录此时为空,可以删除
  17. return file.delete();
  18. }

发表评论

表情:
评论列表 (有 0 条评论,114人围观)

还没有评论,来说两句吧...

相关阅读