我在下面的iText
代码中读取文件并将其添加到主PDF文件中,因此它基本上是在现有PDF的绝对位置添加PDF页面。主PDF中的绝对位置和页码将动态确定。有时,它可能在第1页上使用100,100(x,y)
或在第2页上使用250,250(x,y)
。我遍历每个对象代表PDF文件的PDF对象,然后我将应用业务逻辑将PDF对象转换为PDF文件,即srcPdf
。现在,我需要将此srcPdf
添加到主PDF的绝对位置(此处为pdfStamper
):
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-loop
外部创建,如下所示:PdfReader pdfReader = new PdfReader(new FileInputStream(tempPdf));
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(destPdf));
问题是,如果我在
pdfStamper
之后关闭for-loop
,则会引发RandomAccessSource not opened
异常。如果我在for循环中关闭,则必须在for-loop
中再次创建。你能指出我正确的方向吗? 最佳答案
如我对Extract pdf page and insert into existing pdf的回答所述,使用PdfStamper
只是满足您要求的一种方法。如果您需要处理单个PDF文档,并且您可以从另一个PDF添加单个页面,那么PdfStamper
可能是您的最佳选择,正如我先前的回答所展示的。
但是,您现在指出必须串联多个PDF文件。在这种情况下,使用PdfStamper
不是最佳选择。您应该考虑切换到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的开始处插入每个文档的第一页(并且只有第一页),然后可以执行以下操作: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()
方法添加文档的所有页面。更新资料
似乎您不想插入新页面,但是想要叠加页面:您想在现有内容之上或之下添加页面。
在那种情况下,您确实需要
PdfStamper
,但是您犯了两个关键错误。您在循环内关闭
stamper
。 stamper
关闭后,它也将关闭:您无法再添加任何内容。您需要将stamper.close()
移到循环外。您在循环内关闭了
reader
,但stamper
尚未释放reader
。您应该先释放读者。这在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
对象。