You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java、Thymeleaf和Spring Boot导出PDF失败问题求助

问题分析与解决方案

PDF加载失败的核心原因

你的代码里导致PDF损坏的关键问题有3个:

  1. 流操作冲突:pdfAsc中同时创建本地文件流和response.getOutputStream,但PdfWriter仅绑定了response流,后续关闭本地流会打乱PDF输出逻辑,导致文件内容不完整;
  2. 内容生成错误:直接把getNumAsc()列表转成字符串添加到ListItem,生成的是Troops对象的内存引用(比如[Troops@123, Troops@456]),这种非标准文本会引发PDF解析失败;
  3. 未实现的依赖:exportToPDFAsc中调用的PDF基类export方法无具体实现,执行时会抛出异常中断PDF生成。

改成表格能解决问题吗?

改成表格不仅能让导出内容更规整易读,更关键的是重构代码时可以修正上述流操作和内容生成的错误,从根源解决PDF损坏问题。

iText创建表格的实现教程

下面是修复后的完整PDF导出代码,替换你原来的pdfAsc、exportToPDFAsc等相关方法:

1. 确保依赖正确

如果用Maven,在pom.xml中添加iText依赖:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

2. 修正后的PDF导出方法

// 导出升序表格PDF
@GetMapping("/pdfasc")
public void exportAscToPDF(HttpServletResponse response) throws DocumentException, IOException {
    // 设置响应头,告知浏览器返回PDF文件
    response.setContentType("application/pdf");
    DateFormat dateFormatter = new SimpleDateFormat("yyyy-dd-MM_HH-mm");
    String currentDateTime = dateFormatter.format(new Date());
    String headerValue = "attachment; filename=Troops_Asc_" + currentDateTime + ".pdf";
    response.setHeader("Content-Disposition", headerValue);

    // 初始化iText文档
    com.itextpdf.text.Document document = new com.itextpdf.text.Document();
    PdfWriter.getInstance(document, response.getOutputStream());

    document.open();

    // 创建2列表格(ID、姓名),宽度占满页面
    com.itextpdf.text.pdf.PdfPTable table = new com.itextpdf.text.pdf.PdfPTable(2);
    table.setWidthPercentage(100);

    // 添加表头
    table.addCell(new com.itextpdf.text.Phrase("ID"));
    table.addCell(new com.itextpdf.text.Phrase("姓名"));

    // 循环添加表格数据
    List<Troops> ascList = getNumAsc();
    for (Troops troop : ascList) {
        table.addCell(new com.itextpdf.text.Phrase(String.valueOf(troop.getId())));
        table.addCell(new com.itextpdf.text.Phrase(troop.getFullName()));
    }

    // 将表格加入文档并关闭
    document.add(table);
    document.close();
}

// 导出降序表格PDF
@GetMapping("/pdfdesc")
public void exportDescToPDF(HttpServletResponse response) throws DocumentException, IOException {
    response.setContentType("application/pdf");
    DateFormat dateFormatter = new SimpleDateFormat("yyyy-dd-MM_HH-mm");
    String currentDateTime = dateFormatter.format(new Date());
    String headerValue = "attachment; filename=Troops_Desc_" + currentDateTime + ".pdf";
    response.setHeader("Content-Disposition", headerValue);

    com.itextpdf.text.Document document = new com.itextpdf.text.Document();
    PdfWriter.getInstance(document, response.getOutputStream());

    document.open();

    com.itextpdf.text.pdf.PdfPTable table = new com.itextpdf.text.pdf.PdfPTable(2);
    table.setWidthPercentage(100);

    table.addCell(new com.itextpdf.text.Phrase("ID"));
    table.addCell(new com.itextpdf.text.Phrase("姓名"));

    List<Troops> descList = getNumDes();
    for (Troops troop : descList) {
        table.addCell(new com.itextpdf.text.Phrase(String.valueOf(troop.getId())));
        table.addCell(new com.itextpdf.text.Phrase(troop.getFullName()));
    }

    document.add(table);
    document.close();
}

3. 关键修复说明

  • 统一流操作:仅使用response.getOutputStream作为PDF输出流,避免本地流干扰,确保内容完整写入响应;
  • 规范内容生成:用PdfPTable创建表格,循环遍历Troops列表逐个添加单元格数据,避免对象toString的无效内容;
  • 移除无效代码:删除未实现的PDF基类、DataPDFExporter等冗余代码,直接在Controller方法中完成PDF生成逻辑。

4. 确保Troops类有getter方法

你的Troops类需要提供获取字段的方法,示例如下:

public class Troops {
    private String fullName;
    private int id;

    public Troops(String fullName, int id) {
        this.fullName = fullName;
        this.id = id;
    }

    public String getFullName() {
        return fullName;
    }

    public int getId() {
        return id;
    }
}

内容的提问来源于stack exchange,提问作者Neet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 03:45:38