itextpdf 的基本使用

823人浏览 / 0人评论

参考

https://blog.csdn.net/lyf_ldh/article/details/99955292

引入依赖

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

示例

PdfUtils.java

import com.google.common.collect.Lists;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import me.zhengjie.modules.document.domain.StandardDetail;
import me.zhengjie.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.util.IOUtils;

import java.io.*;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author 风仔
 * @Date 2021/11/19
 * @Version 1.0
 * @Description:
 **/
public class PdfUtils {

    /**
     * 将数据写到PDF文件
     *
     * @param target 目标路径
     * @param data   原始数据
     */
    public static void writeToPdf(String target, List<StandardDetail> data) {
        try {
            // A4纸大小
            //Rectangle pageSize = new Rectangle(595.0F, 842.0F);
            //Document document = new Document(pageSize, 30, 30, 50, 50);
            //Document document = new Document(PageSize.A4);
            Document document = new Document(PageSize.A4.rotate(), 15, 15, 25, 15);
            target = target.replace(".pdf", "-1.pdf");
            File file = new File(target);
            // 使用PDFWriter进行写文件操作
            PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
            // 添加标题
            Paragraph paragraph = new Paragraph("评分详情表", new Font(getBaseFont(), 15, Font.BOLD));
            paragraph.setAlignment(Element.ALIGN_CENTER);
            paragraph.setSpacingAfter(10f);
            document.add(paragraph);
            // 添加表格
            PdfPTable table = addTable();
            // 单元格
            PdfPCell cell;
            // 处理数据
            Map<Long, List<StandardDetail>> map1 = data.stream().collect(Collectors.groupingBy(StandardDetail::getId1));
            Long[] objects1 = map1.keySet().toArray(new Long[0]);
            for (Long o1 : objects1) {
                List<StandardDetail> list1 = map1.get(o1);
                // 类别
                cell = getVerticalCell(list1.get(0).getId1Name());
                // 行合并
                cell.setRowspan(list1.size());
                table.addCell(cell);
                Map<Long, List<StandardDetail>> map2 = list1.stream().collect(Collectors.groupingBy(StandardDetail::getId2));
                for (Long o2 : sort(map2.keySet().toArray(new Long[0]))) {
                    List<StandardDetail> list2 = map2.get(o2);
                    if (CollectionUtils.isNotEmpty(list2)) {
                        // 项目
                        cell = getVerticalCell(list2.get(0).getId2Name());
                        cell.setRowspan(list2.size());
                        table.addCell(cell);
                        Map<Long, List<StandardDetail>> map3 = list2.stream().collect(Collectors.groupingBy(StandardDetail::getId2));
                        Long[] objects3 = map3.keySet().toArray(new Long[0]);
                        for (Long o3 : objects3) {
                            List<StandardDetail> list3 = map3.get(o3);
                            if (CollectionUtils.isNotEmpty(list3)) {
                                for (StandardDetail standardDetail : list3) {
                                    // 内容
                                    cell = getContentCell(standardDetail.getId3Name());
                                    table.addCell(cell);
                                    // 标准分值
                                    cell = getCell(standardDetail.getScore().toString());
                                    table.addCell(cell);
                                    // 评分原则
                                    cell = getRuleCell(standardDetail.getContent());
                                    table.addCell(cell);
                                    // 评审描述
                                    cell = getContentCell(standardDetail.getReason());
                                    table.addCell(cell);
                                    // 实际得分
                                    cell = getCell(String.valueOf(standardDetail.getScore() - standardDetail.getDeduction()));
                                    table.addCell(cell);
                                }
                            }
                        }
                    }
                }
            }
            document.add(table);
            document.close();
            addPageNum(target, target.replace("-1.pdf", "-2.pdf"));
            file.delete();
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成表格对象
     *
     * @return PdfPTable
     */
    private static PdfPTable addTable() {
        PdfPTable table = new PdfPTable(7);
        // 单元格
        PdfPCell cell;
        cell = getCell("类别");
        table.addCell(cell);
        cell = getCell("项目");
        table.addCell(cell);
        cell = getCell("内容");
        table.addCell(cell);
        cell = getCell("标准分值");
        table.addCell(cell);
        cell = getCell("评分原则");
        table.addCell(cell);
        cell = getCell("评审描述");
        table.addCell(cell);
        cell = getCell("实际得分");
        table.addCell(cell);
        // 设置列宽
        float[] colWidths = {5f, 5f, 30f, 5f, 30f, 30f, 5f};
        try {
            table.setTotalWidth(colWidths);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return table;
    }

    /**
     * 添加页码
     *
     * @param source 原文件路径
     * @param target 目标文件路径
     */
    private static void addPageNum(String source, String target) {
        try (FileOutputStream fos = new FileOutputStream(target)) {
            // 新建文档,默认A4大小
            Document document = new Document(PageSize.A4);
            PdfWriter writer = PdfWriter.getInstance(document, fos);
            // 设置页面监听事件,必须在open方法前
            writer.setPageEvent(new PageNumPdfPageEvent());
            document.open();
            // PDF内容体
            PdfContentByte pdfContent = writer.getDirectContent();
            // 读取 源PDF文件,进行一页一页复制,才能触发 添加页码的  页面监听事件
            PdfReader reader = new PdfReader(source);
            // 获取 源文件总页数
            int num = reader.getNumberOfPages();
            // 页面数是从1开始的
            for (int i = 1; i <= num; i++) {
                document.newPage();
                // 设置空页码进行展示
                writer.setPageEmpty(false);
                PdfImportedPage page = writer.getImportedPage(reader, i);
                // 复制好的页面,添加到内容去,触发事件监听
                pdfContent.addTemplate(page, 0, 0);
            }
            document.close();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        imageWatermark(target, target.replace("-2.pdf", ".pdf"));
    }

    /**
     * 添加图片水印
     *
     * @param inputPath  原文件路径
     * @param outputPath 目标文件路径
     */
    public static void imageWatermark(String inputPath, String outputPath) {
        PdfReader reader = null;
        PdfStamper stamp = null;
        try {
            reader = new PdfReader(inputPath);
            stamp = new PdfStamper(reader, new FileOutputStream(outputPath));
            PdfGState gs1 = new PdfGState();
            gs1.setFillOpacity(0.1f);
            String s = Objects.requireNonNull(PdfUtils.class.getClassLoader().getResource("")).toString();
            s = s.replace("file:/", "");
            s = s.replace("eladmin-common", "eladmin-system");
            s = s.replace("classes/", "classes/image/logo.png");
            Image image = Image.getInstance(IOUtils.toByteArray(new FileInputStream(s)));
            int n = reader.getNumberOfPages();
            for (int i = 1; i <= n; i++) {
                PdfContentByte pdfContentByte = stamp.getOverContent(i);
                pdfContentByte.setGState(gs1);
                image.setAbsolutePosition(180, 300);
                // 等比缩放 100为原本大小
                image.scalePercent(200);
                // 旋转角度 正数向左,负数向右
                //image.setRotationDegrees(45);
                pdfContentByte.addImage(image);
            }
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        } finally {
            try {
                stamp.close();
                reader.close();
                new File(inputPath).delete();
            } catch (DocumentException | IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 生成常规单元格
     *
     * @param value 单元格内容
     * @return PdfPCell
     */
    private static PdfPCell getCell(String value) {
        PdfPCell cell = new PdfPCell(new Phrase(value, new Font(getBaseFont(), 12)));
        cell.setUseAscender(true);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setBorderColor(BaseColor.GRAY);
        return cell;
    }

    /**
     * 生成垂直单元格
     *
     * @param value 单元格内容
     * @return PdfPCell
     */
    private static PdfPCell getVerticalCell(String value) {
        value = value.replace("  ", " ");
        // 正常字体
        Font font = new Font(getBaseFont(), 12);
        String[] split = value.split(" ");
        PdfPCell cell = new PdfPCell();
        Paragraph number = new Paragraph(split[0], font);
        if (split[0].length() > 1) {
            number.setFirstLineIndent(6);
        } else {
            number.setFirstLineIndent(10);
        }
        cell.addElement(number);
        List<String> list = splitChineseWord(split[1], 2);
        for (String s : list) {
            Paragraph chinese = new Paragraph(s, font);
            chinese.setFirstLineIndent(8);
            cell.addElement(chinese);
        }
        cell.setUseAscender(true);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setBorderColor(BaseColor.GRAY);
        return cell;
    }

    /**
     * 排序
     *
     * @param objects Long[]
     * @return Long[]
     */
    private static Long[] sort(Long[] objects) {
        Long temp;
        for (int i = 0; i < objects.length; i++) {
            //j是数组的最后一个角标
            for (int j = objects.length - 1; j > i; j--) {
                if (objects[j] < objects[j - 1]) {
                    //从后往前进行比较,小数往前,一轮之后最小数就在最前面了
                    temp = objects[j - 1];
                    objects[j - 1] = objects[j];
                    objects[j] = temp;
                }
            }
        }
        return objects;
    }

    /**
     * 将字符串拆分成单个汉字
     *
     * @param str 源字符串
     * @param mod 拆分级别 eg: mod = 1 或 mod = 2 拆分成1个单词, mod = 4 差分成两个单词
     * @return List<String>
     */
    private static List<String> splitChineseWord(String str, int mod) {
        List<String> result = Lists.newArrayList();
        List<String> list = Lists.newArrayList();
        int chLetter = 0;
        byte[] stringToByte;
        int k = 0;
        byte[] temp;
        try {
            temp = new byte[mod];
            stringToByte = str.getBytes("gbk");
            for (int i = 0; i < stringToByte.length; i++) {
                //根据GBK编码,汉字都是小于0,并分为2个byte存放
                if (stringToByte[i] < 0) {
                    if (k < mod - 1) {
                        temp[k] = stringToByte[i];
                        temp[++k] = stringToByte[++i];
                        k++;
                        if (k == mod) {
                            list.add(new String(temp, "gbk"));
                            k = 0;
                        }
                    } else {
                        byte[] emitLetter = new byte[2];
                        emitLetter[0] = stringToByte[i];
                        emitLetter[1] = stringToByte[i + 1];
                        i = i + 1;
                        chLetter = chLetter + 2;
                        result.add(new String(emitLetter, "gbk"));
                    }
                } else {
                    temp[k] = stringToByte[i];
                    k++;
                    if (k == mod) {
                        list.add(new String(temp, "gbk"));
                        k = 0;
                    }
                }
                if (i == stringToByte.length - 1) {
                    byte[] lastData = new byte[k];
                    System.arraycopy(temp, 0, lastData, 0, k);
                    list.add(new String(lastData, "gbk"));
                }
            }
        } catch (UnsupportedEncodingException ex) {
            System.out.println("no gbk");
        }
        if (CollectionUtils.isNotEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
            return list;
        } else {
            return result;
        }
    }

    /**
     * 生成内容单元格
     *
     * @param value 单元格内容
     * @return PdfPCell
     */
    private static PdfPCell getContentCell(String value) {
        PdfPCell cell = new PdfPCell(new Phrase(value, new Font(getBaseFont(), 12)));
        // 设置可以居中
        cell.setUseAscender(true);
        // 设置垂直对齐
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        // 设置水平对齐
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        // 设置缩进
        cell.setIndent(24);
        // 设置行距 param1 * param2
        cell.setLeading(15, 0);
        // 设置内边距
        cell.setPadding(10);
        // 设置边框颜色
        cell.setBorderColor(BaseColor.GRAY);
        return cell;
    }

    /**
     * 生成评审原则单元格
     *
     * @param value 单元格内容
     * @return PdfPCell
     */
    private static PdfPCell getRuleCell(String value) {
        // 正常字体
        Font font = new Font(getBaseFont(), 12);
        PdfPCell cell = new PdfPCell();
        String[] paragraph = new String[0];
        if (StringUtils.isNotBlank(value)) {
            paragraph = value.split(" ");
        }
        Paragraph p;
        for (String s : paragraph) {
            p = new Paragraph(s, font);
            // 首行缩进
            p.setFirstLineIndent(24);
            cell.addElement(p);
        }
        // 设置可以居中
        cell.setUseAscender(true);
        // 设置垂直对齐
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        // 设置水平对齐
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        // 设置行距 param1 * param2
        cell.setLeading(15, 0);
        // 设置内边距
        cell.setPadding(10);
        // 设置边框颜色
        cell.setBorderColor(BaseColor.GRAY);
        return cell;
    }

    /**
     * 生成基础字体
     *
     * @return BaseFont
     */
    private static BaseFont getBaseFont() {
        String s = Objects.requireNonNull(PdfUtils.class.getClassLoader().getResource("")).toString();
        s = s.replace("eladmin-common", "eladmin-system");
        s = s.replace("classes/", "classes/font/仿宋_GB2312.ttf");
        BaseFont baseFont = null;
        try {
            // 中文字体(现在高版本的不支持中文包)
            //baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            baseFont = BaseFont.createFont(s, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        } catch (com.itextpdf.text.DocumentException | IOException e) {
            e.printStackTrace();
        }
        return baseFont;
    }

}

PageNumPdfPageEvent.java

import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import org.springframework.stereotype.Component;

/**
 * @author 风仔
 */
@Component
public class PageNumPdfPageEvent extends PdfPageEventHelper {

    @Override
    public void onEndPage(PdfWriter writer, Document document) {

        try {
            // PDF文档内容
            PdfContentByte pdfContent = writer.getDirectContent();

            pdfContent.saveState();
            pdfContent.beginText();

            int footerFontSize = 11;

            // 解决页码中文无法显示 或者 显示为乱码的问题
            // 但是必须引入jar包 itext-asian-5.2.0.jar
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
            Font fontDetail = new Font(baseFont, footerFontSize, Font.NORMAL);

            pdfContent.setFontAndSize(baseFont, footerFontSize);

            // 页脚的页码 展示
            String footerNum = String.format("%d", writer.getPageNumber());
            Phrase phrase = new Phrase(footerNum, fontDetail);

            // 页码的 横轴 坐标 居中
            float x = (document.left() + document.right()) / 2;
            // 页码的 纵轴 坐标
            float y = document.bottom(-10);
            // 添加文本内容,进行展示页码
            ColumnText.showTextAligned(pdfContent, Element.ALIGN_CENTER, phrase, x, y, 0);

            pdfContent.endText();
            pdfContent.restoreState();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

全部评论