Reordering pages of a PDF using iText7 and C#

Simple PDF page reordering via iText7 and C#.

Reordering pages of a PDF using iText7 and C#
Photo by Scott Graham / Unsplash

Using a byte array and a List<int> you can reorder pages of a PDF via the .CopyPagesTo() function provided by iText7. How this works is a new PDF with pages in the order of the page numbers from the List<int> is created and returned to the caller.

As the list we're going to use is a normal 1 index base, it means page 1 is index of 1 rather than 0. Therefore reversing the order of a document with five pages would use a List<int> like the following:

new List<int> {5, 4, 3, 2, 1}

Then using iText7, we could call the following and have a byte[] returned of the reordered PDF:

public byte[] ReorderPages(byte[] pdf, List<int> order)
{
    using (var inputStream = new MemoryStream(pdf))
    {
        using (var reader = new PdfReader(inputStream))
        {
            using (var outputStream = new MemoryStream())
            {
                using (var writer = new PdfWriter(outputStream))
                {
                    using (var inputDocument = new PdfDocument(reader))
                    {
                        using (var outputDocument = new PdfDocument(writer))
                        {
                            inputDocument.CopyPagesTo(order, outputDocument);
                        }
                    }
                }

                return outputStream.ToArray();
            }
        }
    }
}

As many iText7 Pdf objects implement IDisposable, we have to manually release the unmanaged resources. In the order of above, the resources being managed are:

  1. MemoryStream for reading in the byte array.
  2. PdfReader to read the MemoryStream.
  3. Another MemoryStream to serve as the PDF stream after the pages have been reordered.
  4. PdfWriter to write to the output stream.
  5. A PdfDocument to serve as the input document to copy from.
  6. Another `PdfDocument` to serve as the output document to copy to.

Feel free to swap out the using blocks for .close() if that fits your style. We can also pass a stream instead - removing the need for the first MemoryStream using block.

As an aside, the input list for .CopyPagesTo() is an IList meaning types other than List will work too such as ArrayList.