在for循环中使用PdfStamper的最佳方法
我在iText
代码下面读取文件并将其添加到主PDF文件中,因此它基本上是在绝对位置的现有PDF中添加PDF页面。 主PDF中的绝对位置和页码将动态决定。 有时它可能在第1页上有100,100(x,y)
或第2页有250,250(x,y)
。 我循环遍历每个对象代表PDF文件的PDF对象,然后我将应用业务逻辑将PDF对象转换为PDF文件,即srcPdf
。 现在我需要将这个srcPdf
添加到master 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
之外创建的for-loop
如下所示:
PdfReader pdfReader = new PdfReader(new FileInputStream(tempPdf)); PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(destPdf));
问题是如果我在for-loop
后关闭pdfStamper
它会抛出RandomAccessSource not opened
exception。 如果我关闭内部for循环,我将不得不在for循环中再次创建。 你能指点我正确的方向吗?
正如我在提取pdf页面的答案中所解释并插入到现有的pdf中 ,使用PdfStamper
只是满足您要求的一种方法。 如果您需要操作单个PDF文档 , PdfStamper
可能是您的最佳选择,并且可以从我之前的答案演示中添加来自另一个PDF 的单个页面 。
但是,您现在指出必须连接多个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
对象。
- 如何使用eclipse在pdf中创建波斯语内容
- 如何使用iText在所有文档页面中显示数字PDF签名?
- 将jasper导出为pdf时,NoClassDefFoundError:com / itextpdf / text / DocumentException
- 如何在Java中将ppt文件转换为pdf文件?
- java.lang.NoClassDefFoundError:com / itextpdf / text / DocumentException
- 是否可以使用iText查找文本位置
- 如何使用iText在每个页面上添加总页数?
- 如何从PDF文件中删除所有图像/绘图并仅以Java格式保留文本?
- 使用java密码保护pdf