复制 pdf 时 iText 'java.io.IOException The document has no pages'

iText 'java.io.IOException The document has no pages' while copying pdf

我正在尝试从字节数组复制一个 pdf,并用一个只有一页的 pdf 标记每一页。每次我尝试复制 pdf 并标记每一页时,我都会收到异常 iText 'java.io.IOException The document has no pages'

这是我的代码:

public static ByteArrayOutputStream AddPageTemplate(ByteArrayOutputStream baos){    
    Document document = getDocument();
    ByteArrayOutputStream copyWithTemplateAdded = new   ByteArrayOutputStream();

    try {
        PdfCopy copy = new PdfCopy(document, copyWithTemplateAdded);
        PdfWriter writer = PdfWriter.getInstance(document, copyWithTemplateAdded);
        PdfReader templateReader = new PdfReader(PAGE_TEMPLATE.getInputStream());
        PdfImportedPage templatePage = writer.getImportedPage(templateReader, 1);

        document.open();
        baos.flush();
        PdfReader reader = new PdfReader(baos.toByteArray());
        int n1 = reader.getNumberOfPages();
        PdfImportedPage page;
        PdfCopy.PageStamp stamp;
        for (int i = 1; i <= n1; ++i) {
            page = copy.getImportedPage(reader, i);
            stamp = copy.createPageStamp(page);
            stamp.getUnderContent().addTemplate(templatePage, 0, 0);
            stamp.alterContents();
            copy.addPage(page);
        }
        copyWithTemplateAdded.close();
        reader.close();
        copy.close();
        templateReader.close();
        document.close();
    }
    catch(DocumentException p){
        //todo log error
    }
    catch (IOException e) {
        //todo log error
    }
    return copyWithTemplateAdded;
}

任何解决此问题的帮助都会很棒。我正在使用 itextpdf 5.3.4

您在非常短的代码片段中犯了很多不同的错误。

一个错误导致了错误:您将 copyWithTemplateAdded 创建为 ByteArrayOutputStream 并为两个作者使用相同的 OutputStream

PdfCopy copy = new PdfCopy(document, copyWithTemplateAdded);
PdfWriter writer = PdfWriter.getInstance(document, copyWithTemplateAdded);

这永远行不通:

  • PdfCopy 将字节写入 OutputStream 以将 现有 PDF 复制到新 PDF。
  • PdfWriter 将字节写入 same OutputStream 目的是从头开始创建 new PDF.

结果将是完全损坏的 PDF,因为:

  1. 您正在将 PdfWriterPdfCopy 混合在一起,他们都在写入相同的 OutputStream(想想 The Fly 中的 Jeff Goldblum 以了解会发生什么).
  2. 你从PdfWriter获取导入的页面(意味着所有需要的引用将存储在writer对象中),但你在PdfCopy中使用导入的页面实例(但 copy 没有对该页面所需资源的任何引用)。

IOException 是由于 writer 对象关闭(在 document.close() 时)并且没有添加内容:所有内容都添加到 copy对象。

另一个错误:您在关闭 document.

实例之前关闭了 copy 实例

但最大的错误是您将 PdfCopy(和 PdfWriter)用于可能应该用 PdfStamper 完成的事情。

您的代码灵感从何而来?你能帮我下载 Chapter 6 of my book and take a look at the StampStationery 示例吗?

public void manipulatePdf(String src, String stationery, String dest)
    throws IOException, DocumentException {
    // Create readers
    PdfReader reader = new PdfReader(src);
    PdfReader s_reader = new PdfReader(stationery);
    // Create the stamper
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    // Add the stationery to each page
    PdfImportedPage page = stamper.getImportedPage(s_reader, 1);
    int n = reader.getNumberOfPages();
    PdfContentByte background;
    for (int i = 1; i <= n; i++) {
        background = stamper.getUnderContent(i);
        background.addTemplate(page, 0, 0);
    }
    // CLose the stamper
    stamper.close();
    reader.close();
    s_reader.close();
}

在此示例中,我们有一个现有的 PDF 文件(其路径为 src)和一个我们要添加为每个页面背景的模板(模板的路径为 stationery).我们创建一个 PdfStamper 对象,它将基于现有的 PDF 文档创建一个新文件(新文件的路径将为 dest)。

我们将模板的第一页加载到 PdfImportedPagepage 对象)。我们遍历每一页,并在后台添加 page。此代码直接来自文档,比您编写的代码更容易理解。