Java使用iText7生成PDF,学到啦!

Java资料站

共 5667字,需浏览 12分钟

 ·

2021-11-14 09:09

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达


前言

  我们之前使用js库html2canvas + jspdf实现html转PDF、图片,并下载(详情请戳:html页面转PDF、图片操作记录),大致原理是将页面塞到画布里,以图片的方式放到PDF中,生成的文件比较大,文本记录Java使用iText7生成PDF

 

  iText 7是iText强大的PDF工具包的最新版本,用于PDF生成,PDF编程,处理和操作,如数字签名等

  官方文档:

       https://kb.itextpdf.com/home/it7kb/ebooks

 

  简单生成PDF

  官方文档:

       https://kb.itextpdf.com/home/it7kb/ebooks/itext-7-jump-start-tutorial-for-java

  根据文档说明,我们引入依赖


    
    
    7.1.7



    
    
    
    
        com.itextpdf
        kernel
        ${itext7.version}
    

    
        com.itextpdf
        io
        ${itext7.version}
    

    
        com.itextpdf
        layout
        ${itext7.version}
    

    
        com.itextpdf
        forms
        ${itext7.version}
    

    
        com.itextpdf
        pdfa
        ${itext7.version}
    


 

  代码

package cn.huanzi.qch.util;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.annot.PdfLinkAnnotation;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * itextpdf 工具类
 * iText 7是iText强大的PDF工具包的最新版本,用于PDF生成,PDF编程,处理和操作,如数字签名等。
 * https://kb.itextpdf.com/home/it7kb/ebooks
 */
public class ITextPdfUtil {
    //字体,我这里使用系统自带的simhei黑体
    private static final String FONT = "C:/Windows/Fonts/simhei.ttf";

    //html转pdf
    public static void html2pdf(){
        String html = "";

        //从html文件读取内容
        StringBuilder stringBuilder = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new FileReader("E:\\Java\\html2pdf.html"));){
            for (Object o :  reader.lines().toArray()) {
                stringBuilder.append(o);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        html = stringBuilder.toString();

        try (PdfWriter writer = new PdfWriter("E:\\Java\\html2pdf.pdf");
             PdfDocument pdf = new PdfDocument(writer);
        ){
            //转换器属性设置
            ConverterProperties props = new ConverterProperties();
            //字体
            props.setFontProvider(new FontProvider());
            props.getFontProvider().addFont(ITextPdfUtil.FONT);
            //为img图片配置基础路径
            props.setBaseUri("D:\\XFT User\\Pictures\\");

            //HtmlConverter.convertToDocument
            Document document = HtmlConverter.convertToDocument(html, pdf, props);

            //设置文档属性
            pdf.getDocumentInfo().setAuthor("huanzi-qch");
            pdf.getDocumentInfo().setTitle("IText测试html2pdf");
            pdf.getDocumentInfo().setSubject("XXX公司");
            pdf.getDocumentInfo().setMoreInfo("1","111");
            pdf.getDocumentInfo().setCreator("huanzi");
            pdf.getDocumentInfo().setKeywords("IText");

            //注册事件监听
            pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler());

            //设置字体
            document.setFont(ITextPdfUtil.getPdfFont());

            //页边距
            document.setMargins(0, 0, 0, 0);

            document.close();
            System.out.println("操作完成!");
        }catch (IOException e){
            e.printStackTrace();
            System.err.println("操作异常...");
        }
    }

    //生成简单PDF
    public static void test(){
        //语法糖
        try (PdfWriter writer = new PdfWriter("E:\\Java\\test.pdf");
             PdfDocument pdf = new PdfDocument(writer);
             Document document = new Document(pdf, PageSize.A4.rotate());
        ){

            //设置文档属性
            pdf.getDocumentInfo().setAuthor("huanzi-qch");
            pdf.getDocumentInfo().setTitle("IText测试PDF");
            pdf.getDocumentInfo().setSubject("XXX公司");
            pdf.getDocumentInfo().setMoreInfo("1","111");
            pdf.getDocumentInfo().setCreator("huanzi");
            pdf.getDocumentInfo().setKeywords("IText");

            //注册事件监听
            pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler());

            //设置字体
            document.setFont(ITextPdfUtil.getPdfFont());

            //页边距
            document.setMargins(20, 20, 20, 20);

            //简单文字
            document.add(new Paragraph("简单文字"));
            document.add(new Paragraph("Hello Word!").add(new Tab()).add(new Text("你好!").addStyle(new Style().setFontSize(24))));

            //简单图片
            document.add(new Paragraph("简单图片"));
            document.add(new Image(ImageDataFactory.create("D:\\XFT User\\Pictures\\logo.png")));

            //简单表格
            document.add(new Paragraph("简单表格"));
            Table table = new Table(new float[]{3, 3, 4});
            PdfFont font = ITextPdfUtil.getPdfFont();
            //标题、内容
            process(table, "姓名;年龄;电话号码", font, true);
            for (int i = 0; i < 5; i++) {
                process(table, "张三"+i+";"+(18+i)+";1500000000"+i, font, false);
            }
            document.add(table);

            //超链接
            document.add(new Paragraph("超链接"));
            PdfLinkAnnotation annotation = new PdfLinkAnnotation(new Rectangle(0, 0));
            annotation.setAction(PdfAction.createURI("https://itextpdf.com/"));
            Paragraph p = new Paragraph("更多精彩内容,猛戳:").add(new Link("这里", annotation));
            document.add(p);

            //换一页
            //document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));

            document.close();
            System.out.println("操作完成!");

        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("操作异常...");
        }
    }

    //获取统一字体
    public static PdfFont getPdfFont(){
        PdfFont pdfFont = null;
        try {
            pdfFont = PdfFontFactory.createFont(ITextPdfUtil.FONT, PdfEncodings.IDENTITY_H,true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pdfFont;
    }

    //设置表格内容
    public static void process(Table table, String line, PdfFont font, boolean isHeader) {
        String[] split = line.split(";");
        for (String s : split) {
            Cell cell = new Cell().add(new Paragraph(s).setFont(font));
            if (isHeader) {
                table.addHeaderCell(cell);
            } else {
                table.addCell(cell);
            }
        }
    }

    /**
     * 自定义事件监听
     *
     * 背景颜色
     * 页脚页眉
     * 文字水印
     *
     * 也可以分成多个EventHandler
     */
    protected static class MyEventHandler implements IEventHandler {

        @Override
        public void handleEvent(Event event) {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdfDoc = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            int pageNumber = pdfDoc.getPageNumber(page);
            Rectangle pageSize = page.getPageSize();
            PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);

            //背景颜色
            Color backgroundColor = new DeviceRgb(245, 245, 245);;
            pdfCanvas.saveState()
                    .setFillColor(backgroundColor)
                    .rectangle(pageSize.getLeft(), pageSize.getBottom(),pageSize.getWidth(), pageSize.getHeight())
                    .fill().restoreState();

            //页脚页眉
            PdfFont pdfFont = ITextPdfUtil.getPdfFont();
            String header = "我是页眉";
            String footer = "第 "+pageNumber+" 页";
            pdfCanvas.beginText()
                    .setFontAndSize(pdfFont, 9)
                    .moveText((pageSize.getWidth() / 2) - (pdfFont.getWidth(header) / 200), pageSize.getTop() - 20)
                    .showText(header)
                    .moveText((pdfFont.getWidth(header) / 200) - (pdfFont.getWidth(footer) / 200), -pageSize.getTop() + 30)
                    .showText(footer)
                    .endText();

            //文字水印
            Canvas canvas = new Canvas(pdfCanvas, pdfDoc, page.getPageSize());
            canvas.setFontColor(new DeviceRgb(200, 200, 200));
            canvas.setProperty(20, 20);
            canvas.setFont(pdfFont);
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    canvas.showTextAligned(new Paragraph("我是文字水印").setOpacity(0.8f),(150 + i * 300), (160 + j * 150), pdfDoc.getPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
                }
            }

            pdfCanvas.release();
        }
    }

    //测试
    public static void main(String[] args) {
        test();

        //html2pdf();
    }
}

 

  效果

 

 

  生成的PDF

 

 

   文档属性

 

 

 

 

  HTML转PDF

  官方文档:

https://kb.itextpdf.com/home/it7kb/ebooks/itext-7-converting-html-to-pdf-with-pdfhtml

  pdfHTML是iText 7的一个附加组件,需要添加依赖


    
    
    2.1.4



    
    
    
    
        com.itextpdf
        html2pdf
        ${itext7.html2pdf.version}
    


  代码

  代码同上,仅main测试函数不同!

    //测试
    public static void main(String[] args) {
        //test();

        html2pdf();
    }

  PS:html内容往下拉  

 

  效果

 

 

  html页面




    简单简历
    "Content-Type" content="text/html; charset=utf-8" />
    "cache-control" content="no-cache, no-store, must-revalidate"/>
    "pragma" content="no-cache"/>
    "expires" content="0"/>

    
    



"body" class="main">
    "section">
        "module">
            "list1" style="margin: 0;">基本信息
            "block">
                

XXX//25岁


                

本科/XX学校/XX专业/2014-2018


                

工龄:X年


                

手机:XXXXXXXXXX


                

邮箱:XXXXX@qq.com


                

GitHub:"https://github.com/huanzi-qch">https://github.com/huanzi-qch


                

博客园:"https://www.cnblogs.com/huanzi-qch">https://www.cnblogs.com/huanzi-qch


                

                

求职岗位:Java开发/目标城市:南宁市/期望薪资:面议


                

注:已离职,一个月可到岗


                
                "position: relative;top: -350px;left: 500px;width: 100px;height: 130px;" src="logo.png"/>
            

        


        "module">
            "list1">技能清单
            "block">
                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


                

熟悉XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。


            

        


        "module">
            "list1">工作经历
            "block">
                

XXX技术有限公司/Java开发工程师/2018.01 - 至今


                

参与多个项目开发、测试、部署等工作,包括:


                

1、XXX。


                

2、XXX。


                

3、XXX。


            

        

        "module">
            "list1">项目经历
            "block">
                "list2">项目1
                "block1">
                    

项目名称:XXX(2020-11 —2021-11)


                    

项目介绍:XXXXXXXXXXXXXXX。


                    

技术架构:XXX + XXX + XXX。


                    

职责描述:


                    

1、XXXX。


                    

2、XXXX。


                    

3、XXXX。


                    

4、XXXX。


                

                "list2">项目2
                "block1">
                    

项目名称:XXX(2020-11 —2021-11)


                    

项目介绍:XXXXXXXXXXXXXXX。


                    

技术架构:SpringBoot + Vue + Element-UI + ECharts。


                    

职责描述:


                    

1、XXXX。


                    

2、XXXX。


                    

3、XXXX。


                    

4、XXXX。


                
            
        

        "module">
            "list1">自我评价
            "block">
                

1、XXXX;


                

2、XXXX;


                

3、XXXX;


            
        
    



 

 

  生成的PDF

 

 

  后记

  不管是前端生成PDF,还是后端生成PDF,能实现需求就是好技术!  


  作者 |  huanzi-qch

来源 |  cnblogs.com/huanzi-qch/p/15540276.html


加锋哥微信: java3459  
围观锋哥朋友圈,每天推送Java干货!

浏览 60
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报