iText'java.io.IOException复制pdf

时间:2015-12-22 18:05:19

标签: java itext

我正在尝试从字节数组中复制pdf,并使用包含单个页面的pdf标记每个页面。每当我尝试复制pdf并盖章每页时,我都会得到异常iText'java.io.IOException该文档没有页面'

这是我的代码:

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

1 个答案:

答案 0 :(得分:2)

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

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

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

这永远不会奏效:

  • PdfCopy会将字节写入OutputStream,目的是将现有PDF 复制到新PDF。
  • PdfWriter会将字节写入相同的 OutputStream,目的是从头开始创建新PDF

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

  1. 您正在将PdfWriterPdfCopy混合在一起OutputStream(想想The Fly中的Jeff Goldblum,以了解期待的内容)。
  2. 您从PdfWriter获取导入的页面(意味着所需的所有引用都将存储在writer对象中),但您使用PdfCopy实例中的导入页面(但是copy没有对该页面所需资源的任何引用。)
  3. IOExceptionwriter对象已关闭(document.close()后)并且未添加任何内容的原因:所有内容都已添加到copy对象

    另一个错误:在关闭copy之前关闭document实例。

    但最大的错误是您使用PdfCopy(以及PdfWriter)来处理可能应该使用PdfStamper的内容。

    您从哪里获得代码的灵感?你可以帮我一个忙,然后下载Chapter 6 of my book并查看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。此代码直接来自文档,比您编写的内容更容易理解。