在 for 循环中使用 PdfStamper 的最佳方法

2023-12-01

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

Here pdfStamper是在外部创建的for-loop像下面这样:

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

问题是如果我关闭pdfStamper after for-loop它抛出RandomAccessSource not opened例外。如果我关闭内部 for 循环,我将不得不在内部再次创建for-loop。你能指出我正确的方向吗?


正如我的回答中所解释的提取 pdf 页面并插入到现有 pdf 中, using PdfStamper只是满足您要求的一种方法。PdfStamper如果您需要操纵,可能是您的最佳选择单个 PDF 文档并且可以添加单页 from 另一个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"
};

您需要将每个文档的第一页(并且仅第一页)插入到现有 PDF 的开头,并包含路径"resources/main_document.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()方法添加文档的所有页面。

Update

看来你不想insert新页面,但您想要叠加页面:您要添加的页面在之上 or under现有内容。

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

  1. 你关闭stamper循环内。一旦stamper已关闭,已关闭:您无法向其中添加更多内容。你需要移动stamper.close()在循环之外。
  2. 你关闭reader在循环内部,但是stamper hasn't released the reader然而。你应该free首先是读者。

这显示在超级强加例子:

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循环内的对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 for 循环中使用 PdfStamper 的最佳方法 的相关文章

随机推荐