在for循环中使用PdfStamper的最佳方法 [英] Best approach to use PdfStamper in for loop
问题描述
我有以下 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.
- 你在循环中关闭
压模
。关闭压模
后,它将关闭:您无法再向其中添加任何内容。你需要在循环外移动stamper.close()
。 - 你关闭
读者
在循环内,但压模
尚未发布读者
。您应首先免费读者。
- You close the
stamper
inside the loop. Once thestamper
is closed, it is closed: you can't add any more content to it. You need to movestamper.close()
outside the loop. - You close the
reader
inside the loop, butstamper
hasn't released thereader
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屋!