Skip to content

Extract pages

This is the most representative behaviour-bearing operation in the library: it copies a caller-selected set of page ranges from a source PDF into a brand-new output document via iTextSharp's PdfCopy.

Field Value
Operation ID OP-08
Trigger Caller invokes ExtractPages(DocumentRange documentRange), which opens a PdfReader and delegates to ExtractPageRanges(PdfReader, DocumentRange)
Inputs DocumentRange (a Document paired with one or more PageRange selections)
Outputs PdfResult in Succeeded status, wrapping a new Document containing the extracted pages
Primary components PdfAPI.Core.PdfClientService.ExtractPages, PdfAPI.Core.PdfClientService.ExtractPageRanges
Entry point PdfAPI.Core\Services\PdfClientService.cs

Steps

  1. Read documentRange.Document.File and run Validate PDF bytes to guard it. (BR-01, BR-02, BR-03)
  2. Open a PdfReader over the source bytes and hand it, with the range, to ExtractPageRanges.
  3. Create an output iTextSharp.text.Document and a PdfCopy writer over a MemoryStream; open the document.
  4. Read sourceDocReader.NumberOfPages as the total page count.
  5. For each PageRange:
  6. Skip the range when both start and stop exceed the total page count. (BR-12)
  7. Clamp start and stop down to the total page count when either exceeds it. (BR-13)
  8. When the range IsOriginal (1 to -1), append the entire source document via PdfCopy.AddDocument. (BR-14)
  9. Else when stop >= start or stop == -1, treat -1 as the last page and append pages ascending from start to stop. (BR-15)
  10. Else (stop < start) append pages descending from start down to stop, producing a reversed page order. (BR-16)
  11. Materialise the output bytes, wrap them in a new Document with extension "pdf" via Document.Load(byte[], string), and build a PdfResult in Succeeded status. (BR-17)
  12. Delegates to Load a document.
  13. Set PdfResult.PdfProcessorType = iTextSharp and PdfResult.Message = documentRange.ToString() (the rendered page expression), then return the result. (BR-17, BR-18)

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start(["ExtractPages(documentRange)"]) --> Guard["OP-01: ValidatePdf"]
    Guard --> Open["Open PdfReader,<br>PdfCopy over MemoryStream"]
    Open --> Loop{For each PageRange}
    Loop --> Skip{start and stop<br>both > total?}
    Skip -->|Yes| Loop
    Skip -->|No| Clamp["Clamp start/stop<br>to total pages"]
    Clamp --> Kind{Range kind?}
    Kind -->|Original| CopyAll["AddDocument<br>(entire source)"]
    Kind -->|stop >= start<br>or stop == -1| CopyAsc["Append pages<br>ascending"]
    Kind -->|stop < start| CopyDesc["Append pages<br>descending"]
    CopyAll --> Loop
    CopyAsc --> Loop
    CopyDesc --> Loop
    Loop -->|Done| Wrap["Document.Load(bytes, pdf)"]
    Wrap --> Result(["PdfResult: Succeeded,<br>PdfProcessorType = iTextSharp"])

Failure and edge-case behavior

  • Invalid source PDF bytes abort via PdfException at the guard step (BR-03) before any pages are copied.
  • A page range wholly beyond the document's end contributes no pages to the output and does not raise an error (BR-12).
  • A descending range (stop < start) is not an error condition; it deliberately reverses page order in the output (BR-16).

Sources

  • PdfAPI.Core\Services\PdfClientService.cs
  • PdfAPI.Core\Document.cs
  • PdfAPI.Core\Extract\DocumentRange.cs
  • PdfAPI.Core\Extract\PageRange.cs
  • PdfAPI.Core\PdfResult.cs