在for循环中使用PdfStamper的最佳方法 [英] Best approach to use PdfStamper in for loop

查看:250
本文介绍了在for循环中使用PdfStamper的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 iText 代码来读取文件并将其添加到主PDF文件中,因此它基本上是在绝对位置的现有PDF中添加PDF页面。主PDF中的绝对位置和页码将动态决定。有时它可能在第1页上, 100,100(x,y)或第2页 250,250(x,y) 。我循环遍历每个对象代表PDF文件的PDF对象,然后我将应用业务逻辑将PDF对象转换为PDF文件,即 srcPdf 。现在我需要在主PDF中的绝对位置添加这个 srcPdf (这里是 pdfStamper ):

I have below iText code to read files and adding it into master PDF file, so it is basically adding PDF page in the existing PDF at absolute position. Absolute position and page number in the master PDF will be decided dynamically. Sometimes it could be on page 1 with 100,100(x,y) or page 2 with 250,250(x,y). I am looping through the PDF objects where each object represent PDF file, then I will apply business logic to convert PDF object into PDF file and that is srcPdf. Now I need to add this srcPdf at absolute position in master PDF(which is pdfStamper here):

for(ListOfPdfObject pdfObj: ListOfPdfObjects) {
    // code to create srcPdf so there will be new srcPdf for each iteration. srcPdf is flattened pdf of acro form field pdf.
    PdfReader reader2 = new PdfReader(srcPdf.getAbsolutePath());
    PdfImportedPage page = pdfStamper.getImportedPage(reader2, 1);
    pdfStamper.insertPage(1, reader2.getPageSize(1));
    pdfStamper.getUnderContent(1).addTemplate(page, 100, 100);
    pdfStamper.close(); // problem is here
    reader2.close();
}

这里 pdfStamper 是在 for循环之外创建,如下所示:

Here pdfStamper is created outside for-loop like below:

PdfReader pdfReader = new PdfReader(new FileInputStream(tempPdf));
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(destPdf));

问题是我关闭 pdfStamper 之后 for-loop 它抛出 RandomAccessSource未打开异常。如果我在for循环中关闭,我将不得不在 for-loop 中再次创建。能不能指出我正确的方向。

The problem is if I close pdfStamper after for-loop it throws RandomAccessSource not opened exception. If I close inside for loop I will have to create again inside for-loop. Could you please point me at right direction.

推荐答案

正如我对提取pdf页面并插入现有的pdf ,使用 PdfStamper 只是满足您要求的一种方式。 PdfStamper 可能是您最好的选择,如果您需要操作单个PDF文档,并且可以添加单个页面来自另一个PDF ,正如我之前的回答所示。

As explained in my answer to Extract pdf page and insert into existing pdf, using PdfStamper is only one way to meet your requirement. PdfStamper is probably your best choice if you need to manipulate a single PDF document and it's possible to add a single page from another PDF as my previous answer demonstrates.

但是,您现在表明您必须连接多个PDF文件。在这种情况下,使用 PdfStamper 不是最佳选择。您应该考虑切换到 PdfCopy

However, you now indicate that you have to concatenate multiple PDF files. In that case, using PdfStamper isn't the best choice. You should consider switching to PdfCopy:

假设您有以下文件。

String[] paths = new String[]{
    "resources/to_be_inserted_1.pdf",
    "resources/to_be_inserted_2.pdf",
    "resources/to_be_inserted_3.pdf"
};

您需要插入每个文件的第一页(并且只有第一页)使用路径resources / main_document.pdf启动现有PDF,然后您可以执行以下操作:

You need to insert the first page (and only the first page) of each of these documents at the start of an existing PDF with path "resources/main_document.pdf", then you could do something like this:

Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(dest));
document.open();
PdfReader reader;
for (String path : paths) {
    reader = new PdfReader(path);
    copy.addPage(copy.getImportedPage(reader, 1));
    reader.close();
}
reader = new PdfReader("resources/main_document.pdf");
copy.addDocument(reader);
reader.close();
document.close();

如你所见, addPage()方法添加单个页面,而 addDocument()方法添加文档的所有页面。

As you can see, the addPage() method adds a single page, whereas the addDocument() method adds all the pages of a document.

更新

您似乎不希望插入新网页,但您想要叠加页面:您希望在或 现有内容下添加页面。

It seems that you don't want to insert new pages, but that you want to superimpose pages: you want to add pages on top of or under existing content.

In在这种情况下,你确实需要 PdfStamper ,但是你犯了两个关键错误。

In that case, you indeed need PdfStamper, but you're making two crucial errors.


  1. 你在循环中关闭压模。关闭压模后,它将关闭:您无法再向其中添加任何内容。你需要在循环外移动 stamper.close()

  2. 你关闭读者在循环内,但压模尚未发布 读者 。您应首先免费读者。

  1. You close the stamper inside the loop. Once the stamper is closed, it is closed: you can't add any more content to it. You need to move stamper.close() outside the loop.
  2. You close the reader inside the loop, but stamper hasn't released the reader yet. You should free the reader first.

这显示在 SuperImpose 示例:

public static final String SRC = "resources/pdfs/primes.pdf";
public static final String[] EXTRA =
    {"resources/pdfs/hello.pdf", "resources/pdfs/base_url.pdf", "resources/pdfs/state.pdf"};
public static final String DEST = "results/stamper/primes_superimpose.pdf";

PdfReader reader = new PdfReader(SRC);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST));
PdfContentByte canvas = stamper.getUnderContent(1);
PdfReader r;
PdfImportedPage page;
for (String path : EXTRA) {
    r = new PdfReader(path);
    page = stamper.getImportedPage(r, 1);
    canvas.addTemplate(page, 0, 0);
    stamper.getWriter().freeReader(r);
    r.close();
}
stamper.close();

在这种情况下,我总是将导入的页面添加到主文档的第1页。如果要将导入的页面添加到不同的页面,则需要在循环内创建 canvas 对象。

In this case, I always add the imported pages to page 1 of the main document. If you want to add the imported pages to different pages, you need to create the canvas object inside the loop.

这篇关于在for循环中使用PdfStamper的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆