java使用itext7生成pdf

About itext

在网上看到java关于pdf的第三方库有名的是com.itextpdf的。 

上git上查看,官网的意思是推荐itext7,而itext5只用于修复bug和安全了:

GitHub - itext/itextpdf: [DEPRECATED] Core Java Library + PDF/A, xtra and XML Worker. Only security fixes will be added — please use iText 7[DEPRECATED] Core Java Library + PDF/A, xtra and XML Worker. Only security fixes will be added — please use iText 7 - GitHub - itext/itextpdf: [DEPRECATED] Core Java Library + PDF/A, xtra and XML Worker. Only security fixes will be added — please use iText 7https://github.com/itext/itextpdf

所以,下面是以itext7进行的开发 :

GitHub - itext/itext7: iText 7 for Java represents the next level of SDKs for developers that want to take advantage of the benefits PDF can bring. Equipped with a better document engine, high and low-level programming capabilities and the ability to create, edit and enhance PDF documents, iText 7 can be a boon to nearly every workflow.https://github.com/itext/itext7官网:

The Leading PDF Library for Developers | iTexthttps://itextpdf.com/en

API Doc

Demo

好的,接下里开始上demo:

布局设定

分为title、table、detail三大类,如下用绿色框出来了:

按照这个设定封装对应的数据载体

然后编写工具类

接下测试即可。  

工具类

imageUtil

用于读取base64的图片到byte数组

import org.bouncycastle.util.encoders.Base64;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;

public class ImageUtil {


    /**
     * 校验base64是否合法
     * @param base64
     * @return
     */
    public static boolean safeCheckImgFile(String base64) {
        //check image
        String regex = ",";
        String[] split = base64.split(regex);
        String imageBase64 = split[1];
        byte[] decode = Base64.decode(imageBase64);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode);
        try {
            BufferedImage image = ImageIO.read(byteArrayInputStream);
            if (image != null && image.getWidth() > 0 && image.getHeight() > 0) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
        /*

        Base64Encoder base64Encoder = new Base64Encoder();

        try {
            FileOutputStream fileImageOutputStream = new FileOutputStream("/data/temp/");
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileImageOutputStream);
            base64Encoder.decode(img, bufferedOutputStream);

        } catch (IOException e) {
            e.printStackTrace();
        }
*/

    }

    /**
     * 读取base64字符串,转换为bimage的ytes数组并返回
     * @param base64
     * @return
     */
    public static byte[] readFromImage(String base64) {
        String regex = ",";
        String[] split = base64.split(regex);
        String imageBase64 = split[1];
        byte[] decode = Base64.decode(imageBase64);
     /*   ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode);
        try {
            BufferedImage image = ImageIO.read(byteArrayInputStream);
//            System.out.println(image);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        return decode;

    }
}

PdfUtil_v2

Pdf生成工具

import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.TextAlignment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;

public class PdfUtil_v2 {
    private Logger logger = LoggerFactory.getLogger(PdfUtil_v2.class);
    private MyPdfDocument pdfDocumnt;
    private String file_PATH;//文件绝对路径,包含文件名和后缀,如:I:\\jfqqqq\\test\\1.pdf
    private String font_PATH;
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    private String font_INTERNAL_PATH;

    public PdfUtil_v2(MyPdfDocument pdfDocumnt, String file_PATH, String font_PATH) {
        this.pdfDocumnt = pdfDocumnt;
        this.file_PATH = file_PATH;
        this.font_PATH = font_PATH;
        File directory = new File("src/main/resources");
        try {
            String resourcesPath = directory.getCanonicalPath();
            font_INTERNAL_PATH = resourcesPath + "/fonts/SimSun-01.ttf";
            logger.debug("配置的字体地址:{}, 工程预备的字体地址:{}", font_PATH, font_INTERNAL_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 生成pdf,注意:会覆盖
     *
     * @return
     */
    public File generate() {
        Document document = null;
        try {
            createFilePath(file_PATH, false);
            PdfWriter pdfWriter = new PdfWriter(file_PATH);
            PdfDocument pdfDocument = new PdfDocument(pdfWriter);
            PdfFont font = getPdfFont();//PdfFontFactory.createFont(font_PATH);
            document = new Document(pdfDocument).setFont(font);
            writeHeader(document);
            writeStaticsGrid(document);
            staticsDetails(document);
//                document.close();
            return new File(file_PATH);
//            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document != null) {
                document.close();
            }
        }
        return null;
    }

    private PdfFont getPdfFont() {
        PdfFont font = null;
        try {
            font = PdfFontFactory.createFont(font_PATH);
        } catch (IOException e) {
            logger.error("{} 字体文件不存在!即将采用更称默认字体,默认路径:{}", font_PATH, font_INTERNAL_PATH);
            synchronized (this) {
                font_PATH = font_INTERNAL_PATH;
            }
        }
        if (font == null) {
            try {
                font = PdfFontFactory.createFont(font_PATH);
            } catch (IOException e) {
                logger.error("{} 默认的字体文件不存在!即将采用itext7默认内置字体!不支持中文!", font_INTERNAL_PATH);
            }

        }
        if (font == null) {
            try {
                font = PdfFontFactory.createFont();
            } catch (IOException e) {
                logger.error("", e);
                e.printStackTrace();
            }
        }

        return font;
    }

    public void writeHeader(Document document) {
        Paragraph paragraphTitle = new Paragraph(pdfDocumnt.getTitle());
        paragraphTitle.setFontSize(22);

        Paragraph paragraphBatchName = new Paragraph("(" + pdfDocumnt.getSmallTitle() + ")");
        paragraphBatchName.setFontSize(12);

        Paragraph header = new Paragraph();
        header.setTextAlignment(TextAlignment.CENTER);
        header.add(paragraphTitle);
        header.add(paragraphBatchName);

        document.add(header);

        Table table = new Table(2);
        table.useAllAvailableWidth();
        Cell cell = new Cell(1, 1);
        cell.setBorder(Border.NO_BORDER);
        cell.setTextAlignment(TextAlignment.LEFT);
        cell.add(new Paragraph(pdfDocumnt.getTopLeft()));
        table.addCell(cell);

        cell = new Cell(1, 1);
        cell.setBorder(Border.NO_BORDER);
        cell.setTextAlignment(TextAlignment.RIGHT);
        cell.add(new Paragraph(pdfDocumnt.getTopRight()));
        table.addCell(cell);

        Border border = new SolidBorder(ColorConstants.RED, 2.0f);
        table.setBorderBottom(border);
        document.add(table);
        document.add(new Paragraph());
        //

    }

    public void writeStaticsGrid(Document document) {
        //开头描述
        Paragraph paragraphParent = new Paragraph();
        PdfTable pdfTable = pdfDocumnt.getTable();
        List<PdfTable.MyParagrah> beforeBegin = pdfTable.getBeforeBegin();
        for (PdfTable.MyParagrah begin : beforeBegin) {
            paragraphParent.add(new Paragraph(begin.getContent()).setFontColor(begin.getColor()));
        }
        document.add(paragraphParent);

        //统计表格
        LinkedList<PdfTable.Header> headers = pdfTable.getHeaders();
        Table table = new Table(headers.size());
        table.setWidth(500);
        for (PdfTable.Header header : headers) {
            table.addHeaderCell(header.getTitle());
        }
        List<PdfTable.MyLine> lines = pdfTable.getLines();
        for (PdfTable.MyLine line : lines) {
            for (PdfTable.Header header : headers) {
                table.addCell(new Paragraph(line.getCell(header.getCode()).getValue()));
            }
        }
        document.add(table);

        //空一行
        document.add(new Paragraph());

        //注意点描述
        List<String> pations = pdfTable.getPations();
        document.add(new Paragraph("注:").setFontColor(ColorConstants.RED));
        for (String pation : pations) {
            document.add(new Paragraph(pation).setFontColor(ColorConstants.RED));
        }
    }

    public void staticsDetails(Document document) {
        document.add(new Paragraph("报告详情").setFontSize(18));
        int questionNum = 0;

        List<PdfDetail> details = pdfDocumnt.getDetails();
        for (PdfDetail detail : details) {
            questionNum += 1;
//        addDetails(document, "问题1", "  " + checkValue, 12);
            addDetailsNextLine(document, "问题" + questionNum, "", 15, false);
            Table table = new Table(1);
            table.useAllAvailableWidth();

            List<PdfDetail.MyEntry> items = detail.getItems();
            for (PdfDetail.MyEntry item : items) {
                if (item.getEntryType() == PdfDetail.EntryType.STRING) {
                    addDetailsInLine(table, item.getKey(), item.getVal(), null);
                } else if (item.getEntryType() == PdfDetail.EntryType.IMAGE) {
                    addDetailsInLine(table, item.getKey(), "", null);
                    Image image = readByBase64(item.getVal());
                    image.setTextAlignment(TextAlignment.CENTER);
                    image.setAutoScale(true);
                    table.addCell(image);
                }

            }
            document.add(table);

            //这段代码注释了,这里演示的是直接给document增加图片
//            Image image = readByBase64(item.getVal());
//            image.setTextAlignment(TextAlignment.CENTER);
//            image.setAutoScale(true);
//            document.add(image);
//            document.add(new Paragraph(""));//增加一个空行
        }

    }

    private Image readByBase64(String base64) {
        byte[] bytes = ImageUtil.readFromImage(base64);
        Image image = new Image(ImageDataFactory.create(bytes));
        return image;

    }

    private void addDetailsInLine(Table table, String key, String value, Integer fontSize) {
        Paragraph paragraph = new Paragraph(key + ":  " + value);
        paragraph.setMarginLeft(20);
        if (fontSize != null) {
            paragraph.setFontSize(fontSize);
        }
        Cell cell = new Cell();
        cell.add(paragraph);
        cell.setBorder(Border.NO_BORDER);
        table.addCell(cell);
    }

    private void addDetailsNextLine(Document document, String key, String value, Integer fontSize, boolean useMaoHao) {
        String content = key + (useMaoHao ? ":" : "") + value;
        Paragraph paragraph = new Paragraph(content);
        paragraph.setMarginLeft(3);
        if (fontSize != null) {
            paragraph.setFontSize(fontSize);
        }
        document.add(paragraph);
    }

    public static File createFilePath(String path, boolean createFile) {
        File file = new File(path);
        if (!file.exists()) {
            if (file.isDirectory()) {
                file.mkdirs();
            } else {
                File parentFile = file.getParentFile();
                parentFile.mkdirs();
                try {
                    if (createFile) {
                        file.createNewFile();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
//                return parentFile;
            }
        }

        return file;
    }

}

用于携带pdf数据的实体类

MyPdfDocument

pdf数据载体

import java.util.List;

public class MyPdfDocument {
    private String title;
    private String smallTitle;
    private String topLeft;
    private String topRight;
    private PdfTable table;
    private List<PdfDetail> details;

    public MyPdfDocument() {
    }

    public String getTitle() {
        return title;
    }

    public String getSmallTitle() {
        return smallTitle;
    }

    public void setSmallTitle(String smallTitle) {
        this.smallTitle = smallTitle;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTopLeft() {
        return topLeft;
    }

    public void setTopLeft(String topLeft) {
        this.topLeft = topLeft;
    }

    public String getTopRight() {
        return topRight;
    }

    public void setTopRight(String topRight) {
        this.topRight = topRight;
    }

    public PdfTable getTable() {
        return table;
    }

    public void setTable(PdfTable table) {
        this.table = table;
    }

    public List<PdfDetail> getDetails() {
        return details;
    }

    public void setDetails(List<PdfDetail> details) {
        this.details = details;
    }
}

PdfDetail

MyPdfDocument中的detail数据载体

import java.util.LinkedList;
import java.util.List;

public class PdfDetail {
    private List<MyEntry> items = new LinkedList<>();

    public PdfDetail addItem(String key, String value) {
        items.add(new MyEntry(key, value));
        return this;
    }

    public PdfDetail addItem(String key, String value, EntryType type) {
        items.add(new MyEntry(key, value, type));
        return this;
    }
    public List<MyEntry> getItems() {
        return items;
    }

    public static enum EntryType{
        IMAGE, STRING
    }

    public static class MyEntry{
        private EntryType entryType = EntryType.STRING;
        private String key;
        private String val;

        public MyEntry(String key, String val) {
            this.key = key;
            this.val = val;
        }

        public MyEntry(String key, String val, EntryType type) {
            this.key = key;
            this.val = val;
            this.entryType = type == null ? entryType : type;
        }

        public EntryType getEntryType() {
            return entryType;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getVal() {
            return val;
        }

        public void setVal(String val) {
            this.val = val;
        }
    }
}

PdfTable

MyPdfDocument中的table数据载体

import com.itextpdf.kernel.colors.Color;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class PdfTable {
    private List<MyParagrah> beforeBegin;
    private LinkedList<Header> headers;
    private List<MyLine> lines;
    private List<String> pations;

    public static class MyParagrah {
        private String content;
        private Color color;//ColorConstants.BLACK

        public MyParagrah(String content, Color color) {
            this.content = content;
            this.color = color;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }
    }

    public static class MyCell {
        private int headerCode;
        private String value;

        public MyCell(int headerCode, String value) {
            this.headerCode = headerCode;
            this.value = value;
        }

        public int getHeaderCode() {
            return headerCode;
        }

        public void setHeaderCode(int headerCode) {
            this.headerCode = headerCode;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    public static class MyLine {
        private Map<Integer, MyCell> cells = new HashMap<>();

        public MyLine addCell(MyCell cell) {
            cells.put(cell.getHeaderCode(), cell);
            return this;
        }

        public Map<Integer, MyCell> getCells() {
            return cells;
        }

        public MyCell getCell(int headerCode) {
            return cells.get(headerCode);
        }
    }

    public static class Header {
        private int code;
        private String title;

        public Header(int code, String title) {
            this.code = code;
            this.title = title;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }

    public List<MyParagrah> getBeforeBegin() {
        return beforeBegin;
    }

    public void setBeforeBegin(List<MyParagrah> beforeBegin) {
        this.beforeBegin = beforeBegin;
    }

    public LinkedList<Header> getHeaders() {
        return headers;
    }

    public void setHeaders(LinkedList<Header> headers) {
        this.headers = headers;
    }

    public List<MyLine> getLines() {
        return lines;
    }

    public void setLines(List<MyLine> lines) {
        this.lines = lines;
    }

    public List<String> getPations() {
        return pations;
    }

    public void setPations(List<String> pations) {
        this.pations = pations;
    }
}

测试类

   @Test
    public void testHelper() {
        MyPdfDocument myPdfDocument = new MyPdfDocument();
        myPdfDocument.setTitle("jfqqqqq的监测报告");
        myPdfDocument.setSmallTitle("他很帅");
        myPdfDocument.setTopLeft("jfqqqq的个人管理平台");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        myPdfDocument.setTopRight(simpleDateFormat.format(new Date()));

        PdfTable pdfTable = new PdfTable();
        List<PdfTable.MyParagrah> beforeBegins = new LinkedList<>() {{
            add(new PdfTable.MyParagrah("说点什么好呢,总的来说,这次的监测效果还算不错,我很努力,", ColorConstants.BLACK));
            add(new PdfTable.MyParagrah("值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk", ColorConstants.RED));
            add(new PdfTable.MyParagrah("。嘉奖一下我自己!", ColorConstants.BLACK));
        }};
        pdfTable.setBeforeBegin(beforeBegins);

        LinkedList<PdfTable.Header> headers = new LinkedList<>() {{
            add(new PdfTable.Header(1, "序号"));
            add(new PdfTable.Header(2, "项目"));
            add(new PdfTable.Header(3, "努力"));
            add(new PdfTable.Header(4, "视力"));
        }};
        pdfTable.setHeaders(headers);

        List<PdfTable.MyLine> lines = new LinkedList<>();
        for (int i = 0; i < 5; i++) {
            PdfTable.MyLine line = new PdfTable.MyLine();
            line.addCell(new PdfTable.MyCell(1, "1")).addCell(new PdfTable.MyCell(2, "身高" + i)).addCell(new PdfTable.MyCell(3, "很努力,还行吧" + i)).addCell(new PdfTable.MyCell(4, "哈哈" + i));
            lines.add(line);
        }
        pdfTable.setLines(lines);

        pdfTable.setPations(new LinkedList<String>() {{
            add("1、这里是注释1");
            add("2、这里是注释2");
        }});
        myPdfDocument.setTable(pdfTable);

        List<PdfDetail> details = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            PdfDetail pdfDetail = new PdfDetail();
            String base64Image = "data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM/wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==";
            pdfDetail.addItem("身高", "身高" + i).addItem("努力", "很努力,还行吧" + i).addItem("视力", "哈哈" + i).addItem("截图", base64Image, PdfDetail.EntryType.IMAGE);
            details.add(pdfDetail);
        }
        myPdfDocument.setDetails(details);

        PdfUtil_v2 pdf = new PdfUtil_v2(myPdfDocument, "I:\\tobedelete\\asd.pdf", "F:\\anytest\\pdf\\src\\main\\resources\\fonts\\SimSun-01.ttf");
        pdf.generate();

        System.out.println("success!");
    }

字体文件

想要打印中文需要有中文字体支持的字体文件。可以到C:\Windows\Fonts中找一个中文字体文件给程序使用,或者自己从网上下载。

效果

附加

返回pdf文件时,响应头一般用这两种:

1. content-type:application/pdf
使用比如:

response.setContentType("application/pdf");

2. Content-Disposition:attachment; filename=aa.pdf

使用比如:
response.setHeader("Content-Disposition", "attachment; filename=" + new String((batchName + ".pdf").getBytes(),
        "utf-8"));

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值