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

iTextPDF报Document was closed错误:如何解决及重新打开文档?

解决iTextPDF文档关闭后操作的异常问题

首先,咱们得先搞清楚你这个报错的根源:你在shrinkDocuments方法里处理完每个PDF文档后,立刻调用了pdfDoc.close(),但后续的合并逻辑(或者其他操作)还需要访问这些已经被关闭的PdfDocument对象。iText的文档对象一旦被关闭,就会释放所有关联的资源,绝对不允许再对它做任何操作,这就是抛出Document was closed异常的原因。

核心解决方案:调整文档关闭的时机

你现在的问题是关闭文档太早了,正确的做法是把文档关闭的逻辑移到所有操作(包括合并)完全结束之后。

修改后的shrinkDocuments方法应该去掉内部的close()调用:

private void shrinkDocuments(List<PdfDocument> documentsToBeMerged){
    for (PdfDocument pdfDoc : documentsToBeMerged) {
        for (int p = 1; p <= pdfDoc.getNumberOfPages(); p++) {
            PdfPage page = pdfDoc.getPage(p);
            Rectangle media = page.getCropBox();
            if (media == null) {
                media = page.getMediaBox();
            }
            // Shrink the page to 50%
            Rectangle crop = new Rectangle(0, 0, media.getWidth() / 2, media.getHeight() / 2);
            page.setMediaBox(crop);
            page.setCropBox(crop);
        }
        // 移除这里的pdfDoc.close()!
    }
}

然后在你完成所有合并操作之后,再统一关闭所有源文档和合并后的文档:

// 示例:合并完成后统一关闭资源
private void processDocuments(List<PdfDocument> sourceDocs) {
    // 1. 先执行页面缩小操作
    shrinkDocuments(sourceDocs);
    
    // 2. 执行合并逻辑(这里只是示例,根据你的实际合并代码调整)
    try (PdfDocument mergedDoc = new PdfDocument(new PdfWriter("merged.pdf"))) {
        for (PdfDocument sourceDoc : sourceDocs) {
            sourceDoc.copyPagesTo(1, sourceDoc.getNumberOfPages(), mergedDoc);
        }
    }
    
    // 3. 所有操作完成后,再逐个关闭源文档
    for (PdfDocument doc : sourceDocs) {
        doc.close();
    }
}

如果确实需要重新打开已关闭的文档怎么办?

要注意:一旦PdfDocument被关闭,旧的对象就彻底失效了,无法复用。如果你因为某些原因不得不重新打开,只能从原文件/输入流重新创建新的PdfDocument实例:

// 假设你保存了原始PDF的文件路径列表
List<String> pdfFilePaths = Arrays.asList("doc1.pdf", "doc2.pdf");
List<PdfDocument> reopenedDocs = new ArrayList<>();

for (String path : pdfFilePaths) {
    // 以读写模式打开文档(如果要修改,需要搭配PdfWriter)
    // 建议输出到新文件,避免覆盖原文档
    PdfReader reader = new PdfReader(path);
    PdfWriter writer = new PdfWriter(path.replace(".pdf", "_shrunk.pdf"));
    PdfDocument pdfDoc = new PdfDocument(reader, writer);
    reopenedDocs.add(pdfDoc);
}

// 对重新打开的文档执行缩小操作
shrinkDocuments(reopenedDocs);

// 处理完成后关闭所有文档
for (PdfDocument doc : reopenedDocs) {
    doc.close();
}

额外的最佳实践

  • 尽量使用try-with-resources语法来管理iText的资源(PdfReader、PdfWriter、PdfDocument),它会自动帮你关闭资源,避免手动关闭时机错误:
    try (PdfReader reader = new PdfReader("input.pdf");
         PdfWriter writer = new PdfWriter("output.pdf");
         PdfDocument pdfDoc = new PdfDocument(reader, writer)) {
        // 在这里执行页面缩小、合并等所有操作
        for (int p = 1; p <= pdfDoc.getNumberOfPages(); p++) {
            // 你的页面处理逻辑
        }
    } // 这里会自动关闭所有资源,无需手动调用close()
    
  • 修改PDF时,优先输出到新文件,不要直接覆盖原文件,避免操作失误导致原文档损坏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:22:48