Insert page into existing PDF using itextsharp

2020-02-14 03:39发布

问题:

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();

回答1:

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();
            }
        }
    }
}


回答2:

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();
    }


回答3:

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();


回答4:

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.



回答5:

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);
}