Interface IPdfEditor
- Namespace
- DocToolkit.Extensions.DependencyInjection
- Assembly
- DocToolkit.Extensions.DependencyInjection.dll
Operations on a PDF that already exists — page count, merge, page extraction and document information. Registered by AddDocToolkit(IServiceCollection, Action<DocToolkitOptions>?).
public interface IPdfEditor
Remarks
The only injectable service here that reads a PDF; every other one writes or renders. Nothing on it re-renders, so pages keep the text, fonts and images they arrived with.
Methods
ExtractImages(byte[])
Each page's images, in document order. [0] is page 1.
IReadOnlyList<IReadOnlyList<PdfImage>> ExtractImages(byte[] pdf)
Parameters
pdfbyte[]
Returns
Remarks
A page with no images returns an empty list, which is the ordinary case for a text document rather than a failure.
An image whose pixels could not be re-encoded arrives with a null
PdfImage.Png rather than throwing, so one image in an unusual colour space does
not cost the caller every other image in the document. Check that property before using it.
The bytes are a re-encoding, not the embedded file. They will not be byte-identical
to an original PNG or JPEG, and the byte count usually differs. PdfImage.PixelWidth is
the stored pixel size; Bounds.Width is how large the page draws it, in points.
Exceptions
- ArgumentNullException
pdfis null.- ArgumentException
pdfis empty.- DocumentConversionException
The bytes are not a readable PDF, or it requires a password to open.
ExtractImagesAsync(Stream, CancellationToken)
Each page's images, in document order. [0] is page 1.
Task<IReadOnlyList<IReadOnlyList<PdfImage>>> ExtractImagesAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Remarks
A page with no images returns an empty list, which is the ordinary case for a text document rather than a failure.
An image whose pixels could not be re-encoded arrives with a null
PdfImage.Png rather than throwing, so one image in an unusual colour space does
not cost the caller every other image in the document. Check that property before using it.
The bytes are a re-encoding, not the embedded file. They will not be byte-identical
to an original PNG or JPEG, and the byte count usually differs. PdfImage.PixelWidth is
the stored pixel size; Bounds.Width is how large the page draws it, in points.
Exceptions
- ArgumentNullException
pdfis null.- ArgumentException
pdfis empty.- DocumentConversionException
The bytes are not a readable PDF, or it requires a password to open.
- ArgumentException
sourceis not readable or was empty.- OperationCanceledException
ctwas cancelled.
ExtractPages(byte[], int, int)
A new document holding count pages starting at firstPage.
byte[] ExtractPages(byte[] pdf, int firstPage, int count)
Parameters
pdfbyte[]The document to take pages out of. It is not modified.
firstPageint1-based, because that is how a reader numbers pages.
countintHow many pages to take, starting at
firstPage.
Returns
- byte[]
Exceptions
- ArgumentNullException
pdfis null.- ArgumentOutOfRangeException
The range is not entirely inside the document.
- DocumentConversionException
The bytes are not a readable PDF.
ExtractPagesAsync(Stream, int, int, Stream, CancellationToken)
A new document holding count pages starting at firstPage.
Task ExtractPagesAsync(Stream source, int firstPage, int count, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamfirstPageint1-based, because that is how a reader numbers pages.
countintHow many pages to take, starting at
firstPage.destinationStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
pdfis null.- ArgumentOutOfRangeException
The range is not entirely inside the document.
- DocumentConversionException
The bytes are not a readable PDF.
- OperationCanceledException
ctwas cancelled.
ExtractText(byte[])
Each page's text, in document order. [0] is page 1.
IReadOnlyList<string> ExtractText(byte[] pdf)
Parameters
pdfbyte[]
Returns
Remarks
The index is a list position, not a page number — deliberately unlike this interface's
firstPage parameters, which are 1-based because that is how a reader numbers pages.
A page with no text layer returns an empty string. A scanned document is images, so this returns one empty string per page for one — that is what the file contains, not a failure, and OCR is out of scope. This is the commonest surprise in PDF text extraction, so it is stated here rather than left to be discovered.
Exceptions
- ArgumentNullException
pdfis null.- ArgumentException
pdfis empty.- DocumentConversionException
The bytes are not a readable PDF, or it requires a password to open. A PDF that is merely permission-restricted (an owner password with no user password) is not covered by that: it opens with the default empty password and its text comes back like any other PDF.
ExtractTextAsync(Stream, CancellationToken)
Each page's text, in document order. [0] is page 1.
Task<IReadOnlyList<string>> ExtractTextAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Remarks
The index is a list position, not a page number — deliberately unlike this interface's
firstPage parameters, which are 1-based because that is how a reader numbers pages.
A page with no text layer returns an empty string. A scanned document is images, so this returns one empty string per page for one — that is what the file contains, not a failure, and OCR is out of scope. This is the commonest surprise in PDF text extraction, so it is stated here rather than left to be discovered.
Exceptions
- ArgumentNullException
pdfis null.- ArgumentException
pdfis empty.- DocumentConversionException
The bytes are not a readable PDF, or it requires a password to open. A PDF that is merely permission-restricted (an owner password with no user password) is not covered by that: it opens with the default empty password and its text comes back like any other PDF.
- ArgumentException
sourceis not readable or was empty.- OperationCanceledException
ctwas cancelled.
ExtractWords(byte[])
Each page's words with their positions, in document order. [0] is page 1.
IReadOnlyList<IReadOnlyList<PdfWord>> ExtractWords(byte[] pdf)
Parameters
pdfbyte[]
Returns
Remarks
ExtractText(byte[]) answers what a page says; this answers where it says it — for locating a total on an invoice, or checking a stamp landed inside the margin.
Coordinates are PDF user-space points measured from the page's BOTTOM-left, so a word
near the top of A4 has a Bounds.Bottom near 842 rather than near 0. That is the PDF
convention rather than a screen one, and it is the commonest surprise when these values are
first plotted.
A page with no text layer returns an empty list. A scanned document is images, so this returns one empty list per page for one — that is what the file contains, not a failure, and OCR is out of scope.
Exceptions
- ArgumentNullException
pdfis null.- ArgumentException
pdfis empty.- DocumentConversionException
The bytes are not a readable PDF, or it requires a password to open.
ExtractWordsAsync(Stream, CancellationToken)
Each page's words with their positions, in document order. [0] is page 1.
Task<IReadOnlyList<IReadOnlyList<PdfWord>>> ExtractWordsAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Remarks
ExtractText(byte[]) answers what a page says; this answers where it says it — for locating a total on an invoice, or checking a stamp landed inside the margin.
Coordinates are PDF user-space points measured from the page's BOTTOM-left, so a word
near the top of A4 has a Bounds.Bottom near 842 rather than near 0. That is the PDF
convention rather than a screen one, and it is the commonest surprise when these values are
first plotted.
A page with no text layer returns an empty list. A scanned document is images, so this returns one empty list per page for one — that is what the file contains, not a failure, and OCR is out of scope.
Exceptions
- ArgumentNullException
pdfis null.- ArgumentException
pdfis empty.- DocumentConversionException
The bytes are not a readable PDF, or it requires a password to open.
- ArgumentException
sourceis not readable or was empty.- OperationCanceledException
ctwas cancelled.
InsertPages(byte[], byte[], int)
A copy of target with every page of source inserted so
that the first of them becomes page atPage.
byte[] InsertPages(byte[] target, byte[] source, int atPage)
Parameters
targetbyte[]The document to insert into. It is not modified.
sourcebyte[]The document whose pages are inserted. It is not modified.
atPageint1-based position the first inserted page will occupy.
PageCount + 1appends, which is deliberately allowed - it is the obvious way to say "after everything".
Returns
- byte[]
Exceptions
- ArgumentNullException
Either document is null.
- ArgumentOutOfRangeException
atPageis below 1 or more than one past the last page.- DocumentConversionException
The bytes are not a readable PDF.
InsertPagesAsync(Stream, Stream, int, Stream, CancellationToken)
A copy of target with every page of source inserted so
that the first of them becomes page atPage.
Task InsertPagesAsync(Stream target, Stream source, int atPage, Stream destination, CancellationToken ct = default)
Parameters
targetStreamThe document to insert into. It is not modified.
sourceStreamThe document whose pages are inserted. It is not modified.
atPageint1-based position the first inserted page will occupy.
PageCount + 1appends, which is deliberately allowed - it is the obvious way to say "after everything".destinationStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
Either document is null.
- ArgumentOutOfRangeException
atPageis below 1 or more than one past the last page.- DocumentConversionException
The bytes are not a readable PDF.
- OperationCanceledException
ctwas cancelled.
Merge(IEnumerable<byte[]>)
Joins pdfs into one document, keeping the order given.
byte[] Merge(IEnumerable<byte[]> pdfs)
Parameters
pdfsIEnumerable<byte[]>
Returns
- byte[]
Exceptions
- ArgumentNullException
pdfsis null.- ArgumentException
pdfsis empty; merging nothing would produce a zero-page PDF, which several readers refuse to open.- DocumentConversionException
One of the inputs is not a readable PDF.
MergeAsync(IEnumerable<Stream>, Stream, CancellationToken)
Joins pdfs into one document, keeping the order given.
Task MergeAsync(IEnumerable<Stream> sources, Stream destination, CancellationToken ct = default)
Parameters
sourcesIEnumerable<Stream>destinationStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
pdfsis null.- ArgumentException
pdfsis empty; merging nothing would produce a zero-page PDF, which several readers refuse to open.- DocumentConversionException
One of the inputs is not a readable PDF.
- OperationCanceledException
ctwas cancelled.
PageCount(byte[])
The number of pages in pdf.
int PageCount(byte[] pdf)
Parameters
pdfbyte[]
Returns
Exceptions
- ArgumentNullException
pdfis null.- DocumentConversionException
The bytes are not a readable PDF.
PageCountAsync(Stream, CancellationToken)
The number of pages in pdf.
Task<int> PageCountAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
pdfis null.- DocumentConversionException
The bytes are not a readable PDF.
- OperationCanceledException
ctwas cancelled.
Protect(byte[], PdfProtection)
A copy of pdf encrypted with the passwords and permissions in
protection.
byte[] Protect(byte[] pdf, PdfProtection protection)
Parameters
pdfbyte[]protectionPdfProtection
Returns
- byte[]
Remarks
Set UserPassword if the content must not be read. An owner password alone leaves the document openable by anyone - the permissions are a request a reader is asked to honour, not a lock.
The result cannot be passed back into the other members here; use Unprotect(byte[], string) first.
Exceptions
- ArgumentNullException
pdforprotectionis null.- ArgumentException
pdfis empty, or neither password is set.- DocumentConversionException
It could not be read or written.
ProtectAsync(Stream, Stream, PdfProtection, CancellationToken)
Reads a PDF from source and writes the encrypted copy to
destination. Neither stream is disposed, closed or sought.
Task ProtectAsync(Stream source, Stream destination, PdfProtection protection, CancellationToken ct = default)
Parameters
sourceStreamdestinationStreamprotectionPdfProtectionctCancellationToken
Returns
Exceptions
- ArgumentNullException
Either stream is null, or
protectionis null.- ArgumentException
A stream is unusable, or neither password is set.
- OperationCanceledException
ctwas cancelled.- DocumentConversionException
It could not be read or written.
ReadMetadata(byte[])
The document information pdf carries.
PdfMetadata ReadMetadata(byte[] pdf)
Parameters
pdfbyte[]
Returns
Remarks
An absent entry reads back as null rather than an empty string, so "no title" stays distinguishable from "a title deliberately set to empty".
Exceptions
- ArgumentNullException
pdfis null.- DocumentConversionException
The bytes are not a readable PDF.
ReadMetadataAsync(Stream, CancellationToken)
The document information pdf carries.
Task<PdfMetadata> ReadMetadataAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamThe stream the PDF is read from.
ctCancellationTokenCancels the read.
Returns
Remarks
source is read to its end and is neither disposed, closed nor sought.
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The PDF could not be read.
RemovePages(byte[], int, int)
A new document with count pages removed, starting at
firstPage. The complement of ExtractPages(byte[], int, int):
that one keeps the range, this one keeps everything else.
byte[] RemovePages(byte[] pdf, int firstPage, int count)
Parameters
pdfbyte[]The document to take pages out of. It is not modified.
firstPageint1-based, because that is how a reader numbers pages.
countintHow many pages to drop, starting at
firstPage.
Returns
- byte[]
Exceptions
- ArgumentNullException
pdfis null.- ArgumentOutOfRangeException
The range is not entirely inside the document, or it covers every page - removing everything would leave a zero-page file.
- DocumentConversionException
The bytes are not a readable PDF.
RemovePagesAsync(Stream, int, int, Stream, CancellationToken)
A new document with count pages removed, starting at
firstPage. The complement of ExtractPages(byte[], int, int):
that one keeps the range, this one keeps everything else.
Task RemovePagesAsync(Stream source, int firstPage, int count, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamfirstPageint1-based, because that is how a reader numbers pages.
countintHow many pages to drop, starting at
firstPage.destinationStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
pdfis null.- ArgumentOutOfRangeException
The range is not entirely inside the document, or it covers every page - removing everything would leave a zero-page file.
- DocumentConversionException
The bytes are not a readable PDF.
- OperationCanceledException
ctwas cancelled.
ReorderPages(byte[], IEnumerable<int>)
A copy of pdf with its pages in the order given by
order, which holds 1-based page numbers.
byte[] ReorderPages(byte[] pdf, IEnumerable<int> order)
Parameters
pdfbyte[]The document to reorder. It is not modified.
orderIEnumerable<int>A permutation of every page — the same pages, in a different order. Not a subset, and no repeats.
Returns
- byte[]
Exceptions
- ArgumentNullException
Either argument is null.
- ArgumentException
orderis not a permutation of 1..PageCount.- DocumentConversionException
The bytes are not a readable PDF.
ReorderPagesAsync(Stream, IEnumerable<int>, Stream, CancellationToken)
A copy of pdf with its pages in the order given by
order, which holds 1-based page numbers.
Task ReorderPagesAsync(Stream source, IEnumerable<int> order, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamorderIEnumerable<int>A permutation of every page — the same pages, in a different order. Not a subset, and no repeats.
destinationStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
Either argument is null.
- ArgumentException
orderis not a permutation of 1..PageCount.- DocumentConversionException
The bytes are not a readable PDF.
- OperationCanceledException
ctwas cancelled.
RotatePages(byte[], int, int, int)
A copy of pdf with count pages turned clockwise by
degrees, starting at firstPage.
byte[] RotatePages(byte[] pdf, int firstPage, int count, int degrees)
Parameters
pdfbyte[]The document to turn pages in. It is not modified.
firstPageint1-based, because that is how a reader numbers pages.
countintHow many pages to turn, starting at
firstPage.degreesintHow far to turn, clockwise, as a multiple of 90. Negative turns anticlockwise.
This is relative, not absolute — it adds to whatever rotation the page already carries, so calling it twice with 90 leaves the page at 180.
Returns
- byte[]
Exceptions
- ArgumentNullException
pdfis null.- ArgumentOutOfRangeException
The range is not entirely inside the document, or
degreesis not a multiple of 90.- DocumentConversionException
The bytes are not a readable PDF.
RotatePagesAsync(Stream, int, int, int, Stream, CancellationToken)
A copy of pdf with count pages turned clockwise by
degrees, starting at firstPage.
Task RotatePagesAsync(Stream source, int firstPage, int count, int degrees, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamfirstPageint1-based, because that is how a reader numbers pages.
countintHow many pages to turn, starting at
firstPage.degreesintHow far to turn, clockwise, as a multiple of 90. Negative turns anticlockwise.
This is relative, not absolute — it adds to whatever rotation the page already carries, so calling it twice with 90 leaves the page at 180.
destinationStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
pdfis null.- ArgumentOutOfRangeException
The range is not entirely inside the document, or
degreesis not a multiple of 90.- DocumentConversionException
The bytes are not a readable PDF.
- OperationCanceledException
ctwas cancelled.
Unprotect(byte[], string)
A copy of pdf with its encryption removed.
byte[] Unprotect(byte[] pdf, string password)
Parameters
Returns
- byte[]
Remarks
If the document has an owner password, that is the one required here, even if you also know the user password: removing protection is a modification, which the PDF format reserves for the owner.
Exceptions
- ArgumentNullException
pdforpasswordis null.- ArgumentException
pdfis empty.- DocumentConversionException
The password was wrong, or it could not be read.
UnprotectAsync(Stream, Stream, string, CancellationToken)
Reads an encrypted PDF from source and writes the unprotected copy to
destination. Neither stream is disposed, closed or sought.
Task UnprotectAsync(Stream source, Stream destination, string password, CancellationToken ct = default)
Parameters
sourceStreamdestinationStreampasswordstringctCancellationToken
Returns
Exceptions
- ArgumentNullException
Either stream is null, or
passwordis null.- ArgumentException
A stream is unusable.
- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The password was wrong, or it could not be read.
WithMetadata(byte[], PdfMetadata)
A copy of pdf carrying metadata.
byte[] WithMetadata(byte[] pdf, PdfMetadata metadata)
Parameters
pdfbyte[]metadataPdfMetadata
Returns
- byte[]
Remarks
A null property leaves what the document already had in place, so stamping a title does not silently erase an author. Pass an empty string to clear one.
Exceptions
- ArgumentNullException
Either argument is null.
- DocumentConversionException
The bytes are not a readable PDF.
WithMetadataAsync(Stream, PdfMetadata, Stream, CancellationToken)
A copy of pdf carrying metadata.
Task WithMetadataAsync(Stream source, PdfMetadata metadata, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the PDF is read from.
metadataPdfMetadataThe properties to stamp.
destinationStreamThe stream the updated PDF is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Remarks
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
Exceptions
- ArgumentNullException
An argument is null.
- ArgumentException
sourceis not readable or held no bytes, ordestinationis not writable.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The PDF could not be read or written.