How to merge documents correctly?

Tags: merge documentsconcatenatePdfCopyPdfSmartCopyiText 5

I would like to add a link to an existing pdf that jumps to a coordinate on another page.

I have the following problem when printing the PDF file after merge, the PDF documents get cut off. Sometimes this happens because the documents aren't 8.5 x 11 whereas the page size might be 11 x 17.

Is there some way to detect the page size and then use that same page size for those documents? Or, if not, is it possible to have it fit to page? This is my code:

Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
        BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent();
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
while (iteratorPDFReader.hasNext()) {
    PdfReader pdfReader = iteratorPDFReader.next();
    while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
        Rectangle r = pdfReader.getPageSize(
            pdfReader.getPageN(pageOfCurrentReaderPDF + 1));
        if(r.getWidth()==792.0 && r.getHeight()==612.0)
            document.setPageSize(PageSize.A4.rotate());
        else
            document.setPageSize(PageSize.A4);
        document.newPage();
        pageOfCurrentReaderPDF++;
        currentPageNumber++;
        page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
        cb.addTemplate(page, 0, 0);
        cb.beginText();
        cb.setFontAndSize(bf, 9);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
            + currentPageNumber + " of " + totalPages, 520, 5, 0);
        cb.endText();
    }
    pageOfCurrentReaderPDF = 0;
}
document.close();
Concatenated PDFs

Posted on StackOverflow on Feb 12, 2014 by Sumit Vaidya

Using PdfWriter to merge documents is a bad idea. This has been explained on StackOverflow many times! See for instance Why does the function to concatenate / merge PDFs cause issues in some cases?

Merging documents is done using PdfCopy (or PdfSmartCopy).

If you need an example, see for instance the FillFlattenMerge2 example:

Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
PdfReader reader;
String line = br.readLine();
// loop over readers
    // add the PDF to PdfCopy
    reader = new PdfReader(baos.toByteArray());
    copy.addDocument(reader);
    reader.close();
// end loop
document.close();

In your case, you also need to add page numbers, you can do this in a second go, as is done in the StampPageXofY example:

PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfContentByte pagecontent;
for (int i = 0; i < n; ) {
    pagecontent = stamper.getOverContent(++i);
    ColumnText.showTextAligned(pagecontent, Element.ALIGN_RIGHT,
            new Phrase(String.format("page %s of %s", i, n)), 559, 806, 0);
}
stamper.close();
reader.close();

Or you can add them while merging, as is done in the MergeWithToc example.

Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
PageStamp stamp;
document.open();
int n;
int pageNo = 0;
PdfImportedPage page;
Chunk chunk;
for (Map.Entry<String, PdfReader> entry : filesToMerge.entrySet()) {
    n = entry.getValue().getNumberOfPages();
    for (int i = 0; i < n; ) {
        pageNo++;
        page = copy.getImportedPage(entry.getValue(), ++i);
        stamp = copy.createPageStamp(page);
        chunk = new Chunk(String.format("Page %d", pageNo));
        if (i == 1)
            chunk.setLocalDestination("p" + pageNo);
        ColumnText.showTextAligned(stamp.getUnderContent(),
                Element.ALIGN_RIGHT, new Phrase(chunk),
                559, 810, 0);
        stamp.alterContents();
        copy.addPage(page);
    }
}
document.close();
for (PdfReader r : filesToMerge.values()) {
    r.close();
}
reader.close();

I strongly advise against using PdfWriter to merge documents! As documented, you are throwing away all annotations by adding PdfImportedPage instances to a document using addTemplate(). This is typically not what you want. You're only making it harder on yourself if you insist on using that class. I don't understand why so many people use the wrong approach to merge documents. I blame the unofficial documentation for the popularity of this wrong approach.