8

I'm using the following code to merge PDFs together using iText:

public static void concatenatePdfs(List<File> listOfPdfFiles, File outputFile) throws DocumentException, IOException {
        Document document = new Document();
        FileOutputStream outputStream = new FileOutputStream(outputFile);
        PdfWriter writer = PdfWriter.getInstance(document, outputStream);
        document.open();
        PdfContentByte cb = writer.getDirectContent();
        for (File inFile : listOfPdfFiles) {
            PdfReader reader = new PdfReader(inFile.getAbsolutePath());
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
                document.newPage();
                PdfImportedPage page = writer.getImportedPage(reader, i);
                cb.addTemplate(page, 0, 0);
            }
        }
        outputStream.flush();
        document.close();
        outputStream.close();
    }

This usually works great! But once and a while, it's rotating some of the pages by 90 degrees? Anyone ever have this happen?

I am looking into the PDFs themselves to see what is special about the ones that are being flipped.

Nicholas DiPiazza
  • 10,029
  • 11
  • 83
  • 152

2 Answers2

18

There are errors once in a while because you are using the wrong method to concatenate documents. Please read chapter 6 of my book and you'll notice that using PdfWriter to concatenate (or merge) PDF documents is wrong:

  • You completely ignore the page size of the pages in the original document (you assume they are all of size A4),
  • You ignore page boundaries such as the crop box (if present),
  • You ignore the rotation value stored in the page dictionary,
  • You throw away all interactivity that is present in the original document, and so on.

Concatenating PDFs is done using PdfCopy, 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();

There are other examples in the book.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • 2
    I recognize your name from the itext namespaces. Are you a founder of the itext library? – Nicholas DiPiazza Apr 15 '14 at 18:18
  • 8
    Yes, I'm that Lowagie ;-) – Bruno Lowagie Apr 15 '14 at 18:21
  • Question - copy.addDocument doesn't exist in my version of itext. am I too old? 5.0.6 – Nicholas DiPiazza Apr 15 '14 at 18:23
  • 1
    yep 5.5.0 worked. i thought i was grabbing latest from maven repository but i accidentally mis clicked when i went to copy paste. crap. – Nicholas DiPiazza Apr 15 '14 at 18:26
  • Now a better question - why didn't you have to close your file output stream? Does document.close() do that for you? – Nicholas DiPiazza Apr 15 '14 at 18:27
  • 1
    Yes, `document.close()` also closes the `PdfWriter` instance and the `OutputStream` used by the writer. You can prevent this by using `writer.setCloseStream(false);`. For instance: if you have a `ZipOutputStream` to which you're adding multiple PDFs, you don't want iText to close that stream. – Bruno Lowagie Apr 16 '14 at 06:56
  • The code where I'm calling .close() seems to work, but you're saying then I don't need it. OK. Thanks for the great info. I have confirmed the rotating pages are gone now with your help. – Nicholas DiPiazza Apr 16 '14 at 18:02
  • @NicholasDiPiazza, if you have found your own solution, even using another answer, make your own answer, don't try to [modify another answer](http://stackoverflow.com/review/suggested-edits/4592838). – gunr2171 Apr 16 '14 at 18:04
  • more of an attempt to add on to his answer the correct version of the function i attempted to write above. I can make as a new answer – Nicholas DiPiazza Apr 16 '14 at 18:04
13

In case anyone is looking for it, using Bruno Lowagie's correct answer above, here is the version of the function that does not seem to have the page flipping issue i described above:

public static void concatenatePdfs(List<File> listOfPdfFiles, File outputFile) throws DocumentException, IOException {
        Document document = new Document();
        FileOutputStream outputStream = new FileOutputStream(outputFile);
        PdfCopy copy = new PdfSmartCopy(document, outputStream);
        document.open();
        for (File inFile : listOfPdfFiles) {
            PdfReader reader = new PdfReader(inFile.getAbsolutePath());
            copy.addDocument(reader);
            reader.close();
        }
        document.close();
}
Nicholas DiPiazza
  • 10,029
  • 11
  • 83
  • 152