PDF生成、合并及压缩优化(Java)

依赖文件:

<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itextpdf</artifactId>
  <version>5.5.10</version>
</dependency>
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itext-asian</artifactId>
  <version>5.2.0</version>
</dependency>

创建PDF文件

public PdfReader getPdfBytes(Element element) {
   if (element == null) {
      return null;
   }
   Document document = new Document();
   try {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      PdfWriter writer = PdfWriter.getInstance(document, bos);
      writer.setFullCompression();
      writer.setCompressionLevel(PdfStream.BEST_COMPRESSION);
      document.open();
      document.add(element);
      document.close();
      writer.close();
      return new PdfReader(bos.toByteArray());
   } catch (Exception e) {
      logger.error("getPdfBytes error", e);
   }
   return null;
}

public PdfPTable getUserTableInfo(List<UserDataVo> data) {
   PdfPTable table = new PdfPTable(3);
   table.setWidthPercentage(100);
   float width = PageSize.A4.getWidth() - 40;
   float dataWidth = width / 4;
   float[] columnWidth = new float[] { dataWidth, dataWidth, dataWidth * 2};
   try {
      table.setTotalWidth(columnWidth);
   } catch (Exception e) {
      table.setTotalWidth(width);
   }
   table.addCell(getPdfCellInfo("ID"));
   table.addCell(getPdfCellInfo("用户"));
   table.addCell(getPdfCellInfo("简介"));
   if (CollectionUtils.isNotEmpty(data)) {
      data.stream().forEach(col -> {
         table.addCell(getPdfCellInfo(col.getId()));
         table.addCell(getPdfCellInfo(col.getUserName()));
         table.addCell(getPdfCellInfo(col.getUserText()));
      });
   }
   return table;
}
private PdfPCell getPdfCellInfo(String name) {
   return getPdfCellInfo(name, 1);
}
private PdfPCell getPdfCellInfo(String name, int rowSpan) {
   Font font = getBaseFontInstance();
   PdfPCell cell = new PdfPCell(new Paragraph(StringUtils.defaultString(name), font));
   cell.setHorizontalAlignment(Element.ALIGN_CENTER);
   cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
   if (rowSpan > 1) {
       cell.setRowspan(rowSpan);
   }
   return cell;
}
public static Font getBaseFontInstance() {
   if (baseFont == null) {
      baseFont = getPdfFont();
   }
   return baseFont;
}
private static Font getPdfFont() {
   try {
      BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",
                BaseFont.NOT_EMBEDDED);
      return new Font(bf, 10);
   } catch (Exception e) {
      return null;
   }
}

合并pdf

public byte[] createAndMergeBlobPdf(List<PdfReader> readers) {
    if (CollectionUtils.isEmpty(readers)) {
       return null;
    }
    try {
       ByteArrayOutputStream bos = new ByteArrayOutputStream();
       Document document = new Document();
       if (CollectionUtils.isNotEmpty(readers)) {
          PdfCopy copy = new PdfCopy(document, bos);
          copy.setFullCompression();
          copy.setCompressionLevel(PdfStream.BEST_COMPRESSION);
          document.open();
          for (PdfReader reader: readers) {
             if (reader != null) {
                 int n = reader.getNumberOfPages();
                 for (int j = 1; j <= n; j++) {
                     document.newPage();
                     PdfImportedPage page = copy.getImportedPage(reader, j);
                     copy.addPage(page);
                 }
                 reader.close();
             }
          }
          document.close();
          copy.close();
       }
       return bos.toByteArray();
    } catch (Exception e) {
       logger.error("createAndMergeBlobPdf error", e);
    }
    return null;
}

优化:PdfCopy 更换为PdfSmartCopy,能压缩一半的大小

  • PdfCopy:它会存储两个不同的图片流对象,在索引表中会引用两次,因此虽然是一个相同的图片,但是在不同的页面上会分别显示对应的图片。
  • PdfSmartCopy:经过它处理,会重建索引表,会把这个图片流对象引用到不同的页面上,而这个图片对象只存储了一份。

   PdfCopy处理比较快,但生成的文件的大小会很大,PdfSmartCopy比较慢,会消耗更多内存,但文件大小会很小。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值