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();
}
Here pdfStamper
is created outside for-loop
like below:
PdfReader pdfReader = new PdfReader(new FileInputStream(tempPdf));
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(destPdf));
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.
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.
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
:
Suppose that you have the following files.
String[] paths = new String[]{
"resources/to_be_inserted_1.pdf",
"resources/to_be_inserted_2.pdf",
"resources/to_be_inserted_3.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();
As you can see, the addPage()
method adds a single page, whereas the addDocument()
method adds all the pages of a document.
Update
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 that case, you indeed need PdfStamper
, but you're making two crucial errors.
- 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.
- You close the
reader
inside the loop, but stamper
hasn't released the reader
yet. You should free the reader first.
This is shown in the SuperImpose example:
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();
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.