6

We are using itextsharp to create a single PDF from multiple PDF files. How do I insert a new page into a PDF file that has multiple pages already in the file? When I use add page it is overwriting the existing pages and only saves the 1 page that was selected.

Here is the code that I am using to add the page to the existing PDF:

PdfReader reader = new PdfReader(sourcePdfPath);
                Document document = new Document(reader.GetPageSizeWithRotation(1));
                PdfCopy pdfCopy = new PdfCopy(document, new System.IO.FileStream(outputPdfPath, System.IO.FileMode.Create));
                MemoryStream memoryStream = new MemoryStream();
                PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
                document.AddDocListener(writer);
                document.Open();

                for (int p = 1; p <= reader.NumberOfPages; p++)
                {
                    if (pagesToExtract.FindIndex(s => s == p) == -1) continue;
                    document.SetPageSize(reader.GetPageSize(p));
                    document.NewPage();
                    PdfContentByte cb = writer.DirectContent;
                    PdfImportedPage pageImport = writer.GetImportedPage(reader, p);

                    int rot = reader.GetPageRotation(p);
                    if (rot == 90 || rot == 270)
                    {
                        cb.AddTemplate(pageImport, 0, -1.0F, 1.0F, 0, 0, reader.GetPageSizeWithRotation(p).Height);
                    }
                    else
                    {
                        cb.AddTemplate(pageImport, 1.0F, 0, 0, 1.0F, 0, 0);
                    }

                    pdfCopy.AddPage(pageImport);
                }

                pdfCopy.Close();
Mark Storer
  • 15,672
  • 3
  • 42
  • 80
Rob Banton
  • 61
  • 1
  • 1
  • 4

6 Answers6

6

This code works. You need to have a different file to output the results.

private static void AppendToDocument(string sourcePdfPath1, string sourcePdfPath2, string outputPdfPath)
{
    using (var sourceDocumentStream1 = new FileStream(sourcePdfPath1, FileMode.Open))
    {
        using (var sourceDocumentStream2 = new FileStream(sourcePdfPath2, FileMode.Open))
        {
            using (var destinationDocumentStream = new FileStream(outputPdfPath, FileMode.Create))
            {
                var pdfConcat = new PdfConcatenate(destinationDocumentStream);
                var pdfReader = new PdfReader(sourceDocumentStream1);

                var pages = new List<int>();
                for (int i = 0; i < pdfReader.NumberOfPages; i++)
                {
                    pages.Add(i);
                }

                pdfReader.SelectPages(pages);
                pdfConcat.AddPages(pdfReader);

                pdfReader = new PdfReader(sourceDocumentStream2);

                pages = new List<int>();
                for (int i = 0; i < pdfReader.NumberOfPages; i++)
                {
                    pages.Add(i);
                }

                pdfReader.SelectPages(pages);
                pdfConcat.AddPages(pdfReader);

                pdfReader.Close();
                pdfConcat.Close();
            }
        }
    }
}
markpcasey
  • 559
  • 1
  • 10
  • 18
  • 2
    This code works just need to fix small error for (int i = 0; i < pdfReader.NumberOfPages; i++) needs to be for (int i = 0; i <= pdfReader.NumberOfPages; i++) on two places – Radenko Zec Mar 10 '16 at 08:43
3

I've tried this code, and it works for me, but don't forget to do some validations of the number of pages and existence of the paths you use

here is the code:

private static void AppendToDocument(string sourcePdfPath, string outputPdfPath, List<int> neededPages)
    {

        var sourceDocumentStream = new FileStream(sourcePdfPath, FileMode.Open);
        var destinationDocumentStream = new FileStream(outputPdfPath, FileMode.Create);
        var pdfConcat = new PdfConcatenate(destinationDocumentStream);

        var pdfReader = new PdfReader(sourceDocumentStream);
        pdfReader.SelectPages(neededPages);
        pdfConcat.AddPages(pdfReader);

        pdfReader.Close();
        pdfConcat.Close();
    }
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
sameh.q
  • 1,691
  • 2
  • 23
  • 48
2

You could use something like this, where src is the IEnumerable<string> of input pdf filenames. Just make sure that your existing pdf file is one of those sources. The PdfConcatenate class is in the latest iTextSharp release.

var result = "combined.pdf";
var fs = new FileStream(result, FileMode.Create);
var conc = new PdfConcatenate(fs, true);
foreach(var s in src) {
    var r = new PdfReader(s);
    conc.AddPages(r);
}
conc.Close();
Sergei Z
  • 535
  • 3
  • 10
  • I'm trying to get only certain pages from a source PDF and add them to a existing PDF. The only problem is that it is not adding it to the existing PDF but only over writing it. – Rob Banton Jul 12 '11 at 13:20
  • @Rob: For some reason I didn't get that from the original question. Could your problem be restated as a need to combine certain (including all) pages from source documents into a single file? Meaning that an existing PDF becomes one of those sources with all pages required? – Sergei Z Jul 12 '11 at 14:28
1

Had to even out the page count with a multiple of 4:

private static void AppendToDocument(string sourcePdfPath)
{
    var tempFileLocation = Path.GetTempFileName();
    var bytes = File.ReadAllBytes(sourcePdfPath);

    using (var reader = new PdfReader(bytes))
    {
        var numberofPages = reader.NumberOfPages;
        var modPages = (numberofPages % 4);
        var pages = modPages == 0 ? 0 : 4 - modPages;

        if (pages == 0)
            return;

        using (var fileStream = new FileStream(tempFileLocation, FileMode.Create, FileAccess.Write))
        {
            using (var stamper = new PdfStamper(reader, fileStream))
            {
                var rectangle = reader.GetPageSize(1);
                for (var i = 1; i <= pages; i++)
                    stamper.InsertPage(numberofPages + i, rectangle);
            }
        }
    }

    File.Delete(sourcePdfPath);
    File.Move(tempFileLocation, sourcePdfPath);
}
M. Turnhout
  • 91
  • 1
  • 1
1

PdfCopy is intended for use with an empty Document. You should add everything you want, one page at a time.

The alternative is to use PdfStamper.InsertPage(pageNum, rectangle) and then draw a PdfImportedPage onto that new page.

Note that PdfImportedPage only includes the page contents, not the annotations or doc-level information ("document structure", doc-level javascripts, etc) that page may have originally used... unless you use one with PdfCopy.

A Stamper would probably be more efficient and use less code, but PdfCopy will import all the page-level info, not just the page's contents.

This might be important, it might not. It depends on what page you're trying to import.

Mark Storer
  • 15,672
  • 3
  • 42
  • 80
  • This answer works perfect in my case! I needed to add `n` blank pages to an existing PDF. `PdfStamper.InsertPage` was the way. Thanks! –  Sep 29 '14 at 20:27
0

I know I'm really late to the part here, but I mixed a bit of the two best answers and created a method if anyone needs it that adds a list of source PDF documents to a single document using itextsharp.

private static void appendToDocument(List<string> sourcePDFList, string outputPdfPath)
{
    //Output document name and creation
    FileStream destinationDocumentStream = new FileStream(outputPdfPath, FileMode.Create);
     //Object to concat source pdf's to output pdf
     PdfConcatenate pdfConcat = new PdfConcatenate(destinationDocumentStream);

     //For each source pdf in list...
     foreach (string sourcePdfPath in sourcePDFList)
     {
         //If file exists...
         if (File.Exists(sourcePdfPath))
         {
             //Open the document
             FileStream sourceDocumentStream = new FileStream(sourcePdfPath, FileMode.Open);
             //Read the document
             PdfReader pdfReader = new PdfReader(sourceDocumentStream);

             //Create an int list
             List<int> pages = new List<int>();
             //for each page in pdfReader
             for (int i = 1; i < pdfReader.NumberOfPages + 1; i++)
             {
                 //Add that page to the list
                 pages.Add(i);
             }

             //Add that page to the pages to add to ouput document
             pdfReader.SelectPages(pages);
             //Add pages to output page
             pdfConcat.AddPages(pdfReader);

             //Close reader
             pdfReader.Close();
         }
     }

    //Close pdfconcat
    pdfConcat.Close();
}