java导入pdf(携带动态表格,图片,纯java不需要模板)

发布于:2025-07-30 ⋅ 阅读:(22) ⋅ 点赞:(0)

一、介绍

上一篇文章(java使用freemarker操作word(携带动态表格,图片))https://blog.csdn.net/weixin_45853881/article/details/129298494

紧跟上文,现在不仅需要word,而且还要pdf
在这里插入图片描述

二、准备

导入依赖,这里使用iText 5没有使用iText 7的,追求快点写,至于iText 7,下次一定

<!-- iText 5核心库-->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.2.0</version>
</dependency>
<!--字体-->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

三、实现效果

这里是为了方便查看,就把页码设置在上方了(首页无页码,后续显示页码),下面代码设置的页码就在最下方,所有图片均来源于网络
刚加入了水印设置,懒得截图了也,代码里面有
在这里插入图片描述

四、代码

这里把代码都贴上来了,就把一下操作隐藏了,替换为了手敲,先上代码,后展示样式

package com.wy;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.wy.tools.Staff;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class demo {
    public static void main(String[] args) throws Exception {
        //临时文件目录
        String name = "检查报告-" + UUID.randomUUID();
        FileOutputStream fos = new FileOutputStream("C:\\Users\\admin\\Downloads\\" + name + ".pdf");
        
        // 服务器对客户端的HTTP请求的响应对象
        // HttpServletResponse response
        // ServletOutputStream os = response.getOutputStream();

        //新建文档
        Document document = new Document();
        // 将内存中的 PDF 文档内容转换为二进制数据,处理流
        PdfWriter writer = PdfWriter.getInstance(document, fos);
        writer.setViewerPreferences(PdfWriter.PageModeUseThumbs);
        writer.setPageSize(PageSize.A4);
        // 注册页码事件
        writer.setPageEvent(new PageNumberEvent());
        // 注册水印事件
        writer.setPageEvent(new WatermarkEvent());
 
        document.open();

        // 首页
        part1(document,writer);
        //内容第一页
        document.newPage();
        part3(document);
        // 查看页码设置生效了没
        document.newPage();
        Paragraph con = new Paragraph(" ");
        document.add(con);
        // 关闭文档
        document.close();
    }

    // 首页 封面
    public static void part1(Document document, PdfWriter writer) throws Exception{
        // pdf首页据上方默认无限边界,所有先设置一个空的 好调整位置,不设置空的也可以,使用时间那里的绝对定位进行设置
        // 获取页面尺寸信息(A4默认宽595f,高842f,可根据实际调整)
        float pageWidth = document.getPageSize().getWidth();
        float pageHeight = document.getPageSize().getHeight();
        // 计算居中的坐标(x为页面水平中心)
        float centerX = pageWidth / 2;

        // 空白占据
        Paragraph blank = new Paragraph(" "); //有空格,证明有内容,才可以进行设置间距
        blank.setSpacingBefore(10f); // 上方留出10磅的间距
        blank.setSpacingAfter(10f); // 下方留出10磅的间距
        document.add(blank);

        //logo
        Paragraph title = new Paragraph();
        Image image = Image.getInstance("https://img-home.csdnimg.cn/images/20201124032511.png");
        image.scaleToFit(100, 100); // 调整图片大小
        title.add(new Chunk(image, 18, 0, true));
        Chunk textChunk = new Chunk("CSND", getFont(14, Font.BOLD));
        textChunk.setCharacterSpacing(-2f); //字符间距
        title.add(textChunk);
        title.setIndentationLeft(25f); //左方缩进
        document.add(title);

        //公司
        Paragraph companyName = new Paragraph();
        companyName.add(new Chunk("XXX用户", getFont(32,Font.BOLD)));
        companyName.add(Chunk.NEWLINE);
        companyName.add(new Chunk("文章检测报告", getFont(32,Font.BOLD)));
        companyName.setLeading(0, 2.8f);
        companyName.setAlignment(Element.ALIGN_CENTER);
        companyName.setSpacingBefore(50f); // 上方留出15磅的间距
        document.add(companyName);


        // 时间
        float bottomY = 130f;
        ColumnText ct = new ColumnText(writer.getDirectContent());
        Paragraph time = new Paragraph();
        time.add(new Chunk("官方检测", getFont(18,Font.BOLD)));
        time.add(Chunk.NEWLINE);
        time.add(new Chunk("二〇二五年七月二十九日", getFont(18,Font.BOLD)));
        time.setLeading(0, 1.8f);
        time.setAlignment(Element.ALIGN_CENTER);
        ct.setSimpleColumn(
                centerX - 200f, //左侧
                bottomY, //下方
                centerX + 200f, //右边
                bottomY + 100f //上边
        );
        ct.addElement(time);
        ct.go();
    }

    //内容页
    public static void part3(Document document) throws Exception{
        Paragraph title = new Paragraph();
        title.add(new Chunk("情况汇总表", getFont(18,Font.BOLD)));
        title.setAlignment(Element.ALIGN_CENTER);
        title.setSpacingAfter(20f);
        document.add(title);

        // 创建一个5列的表格
        PdfPTable table = new PdfPTable(5);
        table.setWidthPercentage(100); // 可以减少宽度以避免边缘挤压,根据实际需要设置
        table.setHorizontalAlignment(Element.ALIGN_CENTER); //表格水平居中
        // 设置表格列宽比例
        float[] columnWidths = {1f, 4f, 3f,4f,3f};
        table.setWidths(columnWidths);

        // 添加表头
        String[] headers = {"序号", "姓名", "年龄","职位","图片"};
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Phrase(header, getFont(12,null)));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER); //表头水平居中
            cell.setPadding(5);
            table.addCell(cell);
        }
        // 后续替换为接口对接查询
        List<Staff> list = new ArrayList<>();
        list.add(new Staff("1","张三","30","软件工程师","https://n.sinaimg.cn/sinakd20106/384/w2048h1536/20250517/64b2-bd7d404c74b6c162844f652af698d98e.jpg"));
        list.add(new Staff("2","李四","28","产品经理","https://img1.baidu.com/it/u=1520272912,1660814288&fm=253&fmt=auto&app=138&f=JPEG"));
        list.add(new Staff("3","王五","26","UI设计师","https://www.vipyl.com/user/webimg/2018123/20181231718374.jpg"));
        for (Staff staff : list) {
            addDataCell(table, staff.getId(), getFont(12,null));
            addDataCell(table, staff.getName(), getFont(12,null));
            addDataCell(table, staff.getAge(), getFont(12,null));
            addDataCell(table, staff.getWork(), getFont(12,null));
            Image image = Image.getInstance(staff.getPic());
            image.scaleToFit(100, 100);
            PdfPCell imageCell = new PdfPCell(image, true);
            imageCell.setHorizontalAlignment(Element.ALIGN_CENTER); // 图片水平居中
            imageCell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 图片垂直居中
            imageCell.setPadding(5);
            table.addCell(imageCell);
        }
        // 将表格添加到文档
        document.add(table);
    }

    // 添加数据单元格的辅助方法
    private static void addDataCell(PdfPTable table, String data, Font font) {
        PdfPCell cell = new PdfPCell(new Phrase(data, font));
        cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
        cell.setPadding(5);
        table.addCell(cell);
    }

    // 字体设置
    public static Font getFont(Integer size,Integer type) throws Exception {
        if (size == null) size = 12;
        if (type == null) type = Font.NORMAL;
        BaseFont bf = BaseFont.createFont(
                "STSong-Light",     // 字体名称(宋体)
                "UniGB-UCS2-H", // 字符编码(简体中文)
                BaseFont.NOT_EMBEDDED    // 不嵌入字体(依赖系统字体)
        );

        Font font = new Font(bf, size, type);
        font.setColor(BaseColor.BLACK);
        font.setSize(size);
        return font;
    }

    // 页码事件类
    public static class PageNumberEvent extends PdfPageEventHelper {
        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            // 跳过首页(页码为1时不显示)
            if (writer.getPageNumber() == 1) {
                return;
            }
            PdfContentByte cb = writer.getDirectContent();
            try {
                // 设置字体,使用支持中文的字体(仍需设置,避免其他内容乱码)
                Font font = getFont(10, Font.NORMAL);
                // 设置字体到内容字节
                cb.setFontAndSize(font.getBaseFont(), font.getSize());

                // 计算页码位置(底部居中)
                // 从第2页开始,显示实际页码-1(如第2页显示1,第3页显示2)
                String pageNumber = String.valueOf(writer.getPageNumber() - 1);
                float x = (document.left() + document.right()) / 2;
//                float y = document.bottom() - 15; // 设置底部
                float y = document.top(); // 设置顶部

                // 添加页码
                cb.beginText();
                cb.setTextMatrix(x, y);
                cb.showTextAligned(Element.ALIGN_CENTER, pageNumber, x, y, 0);
                cb.endText();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    
    // 水印事件类
    public static class WatermarkEvent extends PdfPageEventHelper {
        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            // 跳过首页(页码为1时不显示水印)
            if (writer.getPageNumber() == 1) {
                return;
            }
            PdfContentByte canvas = writer.getDirectContentUnder();
            try {
                // 设置水印字体
                Font font = getFont(12, Font.BOLD);
                // 设置水印文本
                String watermarkText = "检测报告";
                // 获取页面尺寸
                Rectangle pageSize = document.getPageSize();
                float width = pageSize.getWidth();
                float height = pageSize.getHeight();

                // 设置水印颜色和透明度
                canvas.saveState();
                // 创建 PdfGState 对象并设置透明度
                PdfGState gs = new PdfGState();
                gs.setFillOpacity(0.5f); // 填充透明度(0-1之间,0完全透明,1完全不透明)
                canvas.setGState(gs); // 将透明度应用到画布

                canvas.setRGBColorFill(200, 200, 200); // 灰色
                canvas.setFontAndSize(font.getBaseFont(), font.getSize());
                canvas.setTextMatrix(0, 0);

                // 设置水印旋转角度
                float angle = 30;

                // 计算水印位置并添加多个水印
                for (float y = -height / 2; y <= height * 1.5; y += 420) {
                    for (float x = -width / 2; x <= width * 1.5; x += 300) {
                        canvas.showTextAlignedKerned(
                                Element.ALIGN_CENTER,
                                watermarkText,
                                x + width / 2,
                                y + height / 2,
                                angle
                        );
                    }
                }
                canvas.restoreState();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

实体类,水点字,就不写在同一个类下了

package com.wy.tools;

public class Staff {
    private String id;
    private String name;
    private String age;
    private String work;
    private String pic;

    // 无参构造方法
    public Staff() {
    }

    // 有参构造方法
    public Staff(String id, String name, String age, String work, String pic) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.work = work;
        this.pic = pic;
    }

    // Getter 和 Setter 方法
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getWork() {
        return work;
    }

    public void setWork(String work) {
        this.work = work;
    }

    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic;
    }

    // 重写 toString 方法
    @Override
    public String toString() {
        return "Study{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", work='" + work + '\'' +
                ", pic='" + pic + '\'' +
                '}';
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到