基于spring boot itext5 生成PDF

1,894 阅读2分钟

需求

1.企业报告以pdf文档格式生成,多个pdf报告的合并以及图片添加到生成的pdf中。

前期准备

1.方案一:基于itext5 进行pdf生成(注意itext7 api 区别较大,尤其在于pdf合并处) 2.方案二:基于jasperreport生成(jasperreport studio 先画pdf表格,生成jasper.xml文件结合java生成pdf,但是此方案注重纯表格pdf样式定制,表格嵌套遍历缺乏灵活性。)

实战

一、itext5

1.gradle依赖配置
implementation 'com.itextpdf:itextpdf:5.5.13.1'
implementation 'com.lowagie:itext:2.1.7.js7'
compile group: 'net.sourceforge.barbecue', name: 'barbecue', version: '1.5-beta1'
2.解决中文不显示问题
  • 2.1 下载所需字体放在resource目录下
  • 2.2 配置字体
private static final String FONT = "fonts/msyh.ttf";
private Font font = new Font(BaseFont.createFont(FONT, 
BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 16, 1);
3.生成PDF报告
  • 3.1 定义document格式及输出的pdf名和输出位置
 Document document = new Document(PageSize.A4, 50f, 50f, 70f, 50f);
 
 PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(test.pdf"));
  • 3.2 Chunk
 Chunk chunk= new Chunk("test", font);
  • 3.3 Paragraph(行,独占一行)
Paragraph paragraph = new Paragraph("test", font);
paragraph.setAlignment(10); //居中
paragraph.setLeading(10); //行距
paragraph.setIndentationLeft(10); //缩进
paragraph.setFirstLineIndent(10);//首行缩进
  • 3.4 Table
PdfPTable table = new PdfPTable(6); 6int itemHeaderWidths[] = {25, 15, 15, 15, 15, 15};// 每列宽度百分比
table.setWidths(itemHeaderWidths);
table.setWidthPercentage(100); //每列宽度按照百分比设置
table.addCell(phraseCell(cell1, 1, font)) //表格每列单元格数据添加

private PdfPCell phraseCell(String value, Integer colspan, Font font) {
     PdfPCell pdfPCell = new PdfPCell(new Phrase(value, font));
     pdfPCell.setHorizontalAlignment(ALIGN_LEFT);
     pdfPCell.setHorizontalAlignment(ALIGN_BOTTOM);
     pdfPCell.setMinimumHeight(23);//单元格高度
     pdfPCell.setColspan(colspan);//合并单元格
     return pdfPCell;
 }
  • 3.5 换行
 document.add(Chunk.NEWLINE);
  • 3.6 下划线
Paragraph paragraph = new Paragraph();
LineSeparator UNDERLINE = new LineSeparator(1, 100, null, Element.ALIGN_CENTER, -2);
paragraph.add(UNDERLINE);
  • 3.7 另起一页
 document.newPage();
  • 3.8 给每一页添加页脚
  • 注意: addFooter(pdfWriter)添加页脚方法必须放在 document.open() 之前否则页脚只在最后一页显示有
  addFooter(pdfWriter);


  private void addFooter(PdfWriter pdfWriter) throws Exception {
        FooterPageEvent footerPageEvent = new FooterPageEvent();
        pdfWriter.setPageEvent(footerPageEvent);
    }



public class FooterPageEvent extends PdfPageEventHelper {

    private static final String FONT = "fonts/msyh.ttf";
    private BaseFont bf;
    private Font contentFont;

    public FooterPageEvent() throws IOException, DocumentException {
        this.bf = BaseFont.createFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        this.contentFont = new Font(bf, 10);
    }

    @SneakyThrows
    public void onEndPage(PdfWriter writer, Document document) {
        PdfContentByte headAndFootPdfContent  = writer.getDirectContent();
        Phrase footer = new Phrase( "第" + writer.getCurrentPageNumber() + “页”, contentFont);
        ColumnText.showTextAligned(headAndFootPdfContent ,
                Element.ALIGN_CENTER,
                footer,
                (document.right() - document.left()) / 2 + document.leftMargin(),
                document.bottom() - 10, 0);
    }
}
4.pdf添加图片
private void addImage(Document document, String imageUrl) throws Exception {
    Resource resource = new FileSystemResource(imageUrl);
    Image img = Image.getInstance(Paths.get(resource.getURI()).toAbsolutePath().toString());
    if (img.getWidth() > img.getHeight())
        img.setRotationDegrees(90);//如果图片宽度小于高度则竖着显示
    img.scalePercent(65);//等比例缩放
    document.add(img);
}
5.合并其他pdf
String first= "C://desktop//pdf//first.pdf";
String second= "C://desktop//pdf//second.pdf";

PdfCopy copy = new PdfCopy(document, new FileOutputStream("merged.pdf"));//合并后的pdf
document.open();
copyPdf(first, copy);
copyPdf(second, copy);
document.close();


private void copyPdf(String location, PdfCopy copy){
	PdfReader reader = new PdfReader(first);
	copy.addDocument(reader);
}