Skip to content

C# / .NET API Reference

The PdfOxide NuGet package wraps the Rust core via LibraryImport-generated P/Invoke (all 881 declarations). NativeAOT-publish-ready and trim-safe. Target frameworks: net8.0, net10.0.

dotnet add package PdfOxide
using PdfOxide.Core;

For other languages see Python, Node.js, Go, or Rust.


Namespaces

using PdfOxide.Core;        // PdfDocument, Pdf, DocumentEditor
using PdfOxide.Extensions;  // LINQ-style extensions
using PdfOxide.Plugins;     // extension points

All types implement IDisposable where appropriate — use using blocks or using declarations.


PdfDocument

Read-only access.

Factory methods

static PdfDocument Open(string path)
static PdfDocument Open(Stream stream)
static PdfDocument OpenFromBytes(ReadOnlySpan<byte> data)
static PdfDocument OpenWithPassword(string path, string password)

Properties

int PageCount { get; }
PdfVersion Version { get; }  // struct { Major, Minor }
bool HasStructureTree { get; }
IReadOnlyList<PdfPage> Pages { get; }  // v0.3.34
PdfPage this[int pageIndex] { get; }   // v0.3.34

PdfPage (v0.3.34)

Lightweight per-page handle with full sync + async surface. Dispatches to the parent document.

public sealed class PdfPage
{
    public int Index { get; }

    public string ExtractText();
    public Task<string> ExtractTextAsync(CancellationToken ct = default);
    public string ToMarkdown();
    public Task<string> ToMarkdownAsync(CancellationToken ct = default);
    public string ToHtml();
    public string ToPlainText();

    public (string Text, float X, float Y, float W, float H)[] ExtractWords();
    public IReadOnlyList<TextLine> ExtractTextLines();
    public IReadOnlyList<Table> ExtractTables();
    public IReadOnlyList<Char> ExtractChars();
    public IReadOnlyList<ImageInfo> ExtractImages();
    public IReadOnlyList<SearchResult> Search(string query, bool caseSensitive = false);
}

Text extraction

string ExtractText(int pageIndex)
Task<string> ExtractTextAsync(int pageIndex, CancellationToken ct = default)
string ExtractAllText()
Task<string> ExtractAllTextAsync(CancellationToken ct = default)

string ToMarkdown(int pageIndex)
string ToMarkdownAll()
string ToHtml(int pageIndex)
string ToHtmlAll()
string ToPlainText(int pageIndex)

Structured

IReadOnlyList<Word> ExtractWords(int pageIndex)
IReadOnlyList<TextLine> ExtractTextLines(int pageIndex)
IReadOnlyList<Char> ExtractChars(int pageIndex)
IReadOnlyList<Span> ExtractSpans(int pageIndex)
IReadOnlyList<Table> ExtractTables(int pageIndex)
IReadOnlyList<Path> ExtractPaths(int pageIndex)

Region-based

string ExtractTextInRect(int pageIndex, float x, float y, float width, float height)
IReadOnlyList<Word> ExtractWordsInRect(int pageIndex, float x, float y, float width, float height)

Images & resources

IReadOnlyList<ImageInfo> ExtractImages(int pageIndex)
IReadOnlyList<FontInfo> GetFonts(int pageIndex)
IReadOnlyList<AnnotationInfo> GetAnnotations(int pageIndex)
IReadOnlyList<FormField> GetFormFields()
PageInfo GetPageInfo(int pageIndex)
IReadOnlyList<SearchResult> SearchPage(int pageIndex, string query, bool caseSensitive = false)
IReadOnlyList<SearchResult> SearchAll(string query, bool caseSensitive = false)

Pdf — creation

static Pdf FromMarkdown(string markdown)
static Pdf FromHtml(string html)
static Pdf FromText(string text)
static Pdf FromImage(string path)
static Pdf FromImageBytes(ReadOnlySpan<byte> data)

void Save(string path)
Task SaveAsync(string path, CancellationToken ct = default)
byte[] ToBytes()

DocumentEditor

static DocumentEditor Open(string path)
static DocumentEditor OpenFromBytes(ReadOnlySpan<byte> data)

// Metadata — properties are get/set
string? Title { get; set; }
string? Author { get; set; }
string? Subject { get; set; }
string? Keywords { get; set; }
int PageCount { get; }

void ApplyMetadata(Metadata metadata)

// Forms
void SetFormFieldValue(string name, string value)
void FlattenForms()

// Save
void Save(string path)
Task SaveAsync(string path, CancellationToken ct = default)
void SaveEncrypted(string path, string userPassword, string ownerPassword)
byte[] ToBytes()

Coverage note: the .NET binding currently exposes document open / read / convert / create, image extraction, form field read/fill/flatten, and metadata editing. Page operations, annotations, rendering, and signatures are available through the Rust core and other bindings; equivalent .NET surface will be added in a future release.


Extensions (LINQ support)

Exported from PdfOxide.Extensions:

IEnumerable<SearchResult> WhereOnPage(this IEnumerable<SearchResult> src, int page)
IEnumerable<IGrouping<int, SearchResult>> GroupByPage(this IEnumerable<SearchResult> src)
IEnumerable<Word> WithinRect(this IEnumerable<Word> src, float x, float y, float w, float h)

Use the existing IReadOnlyList<T> results with LINQ directly:

var hitsByPage = doc.SearchAll("keyword")
    .GroupBy(r => r.Page)
    .OrderBy(g => g.Key);

See extensions guide for the full list.


Plugins

Exposed under PdfOxide.Plugins — inject classifiers, post-processors, or validators into the extraction pipeline. See plugin guide.


Data types

public readonly record struct PdfVersion(int Major, int Minor);

public readonly record struct Char(
    string Text, float X, float Y,
    float FontSize, string FontName, Rect BBox);

public readonly record struct Span(
    string Text, string FontName, float FontSize, Rect BBox);

public readonly record struct Word(
    string Text, float X, float Y, float Width, float Height);

public readonly record struct TextLine(
    string Text, float Y, IReadOnlyList<Span> Spans);

public readonly record struct SearchResult(
    int Page, string Text, float X, float Y, float Width, float Height);

public readonly record struct ImageInfo(
    int Width, int Height, string Format,
    string Colorspace, int BitsPerComponent, byte[] Data);

public readonly record struct FontInfo(
    string Name, string Type, string Encoding,
    bool IsEmbedded, bool IsSubset, float Size);

public readonly record struct AnnotationInfo(
    string Type, string Subtype, string Content,
    float X, float Y, float Width, float Height,
    string? Author, string? LinkUri);

public readonly record struct FormField(
    string Name, string FieldType, string Value, int PageIndex);

public readonly record struct Rect(
    float X, float Y, float Width, float Height);

public readonly record struct PageInfo(
    float Width, float Height, int Rotation,
    Rect MediaBox, Rect CropBox);

public sealed record Metadata(
    string? Title = null,
    string? Author = null,
    string? Subject = null,
    string? Keywords = null);

Exceptions

public class PdfOxideException : Exception
{
    public int Code { get; }
    public string NativeMessage { get; }
}

Thrown on any Rust-side failure. Wrap at system boundaries; interior code should propagate.

Standard .NET exceptions are raised for I/O (FileNotFoundException, UnauthorizedAccessException, etc.) and argument validation (ArgumentOutOfRangeException).


Thread safety

  • PdfDocument read-only methods are thread-safe — use a single document across threads concurrently.
  • DocumentEditor is not thread-safe for writes. Use ReaderWriterLockSlim or serialize to one thread.
  • Pdf creation instances are not intended to be shared across threads.

See the concurrency guide for patterns.

Async pattern

Every I/O-bound or CPU-heavy method has an *Async variant accepting CancellationToken. See the async guide.

NativeAOT

Publish with -p:PublishAot=true. No extra configuration — all P/Invoke is source-generated, no reflection, no dynamic code.

v0.3.38 の追加

DocumentBuilder / PageBuilder / EmbeddedFont

using PdfOxide;

using var font = EmbeddedFont.FromFile("DejaVuSans.ttf");
// Alt: EmbeddedFont.FromBytes(byte[] data, string? name = null)

var bytes = DocumentBuilder.Create()
    .Title("Report").Author("Me")
    .RegisterEmbeddedFont("DejaVu", font)
    .LetterPage()        // or .A4Page() / .Page(width, height)
        .At(72, 720).Font("DejaVu", 12).Text("Hello")
        .Heading(1, "Title")
        .Paragraph("Body text")
        // Annotations
        .LinkUrl("https://example.com")
        .LinkPage(2)
        .LinkNamed("glossary")
        .Highlight(1.0, 1.0, 0.0)
        .Underline(0.0, 0.0, 1.0)
        .Strikeout(1.0, 0.0, 0.0)
        .Squiggly(1.0, 0.5, 0.0)
        .StickyNote("Review this")
        .StickyNoteAt(300, 720, "Positioned note")
        .Stamp(StampType.Approved)
        .FreeText(100, 500, 200, 50, "Comment")
        .Watermark("DRAFT")
        .WatermarkConfidential()
        .WatermarkDraft()
        // AcroForm widgets
        .TextField("name", 150, 400, 200, 20, defaultValue: "Jane Doe")
        .Checkbox("agree", 72, 380, 15, 15, checkedValue: true)
        .ComboBox("country", 150, 360, 200, 20, new[] { "US", "UK" }, selected: "US")
        .RadioGroup("tier", new[] { ("free", 72f, 340f, 15f, 15f), ("pro", 120f, 340f, 15f, 15f) }, selected: "pro")
        .PushButton("submit", 72, 300, 80, 25, caption: "Submit")
        // Graphics primitives
        .Rect(50, 270, 500, 2)
        .FilledRect(50, 260, 500, 2, 0.9, 0.9, 0.9)
        .Line(50, 250, 550, 250)
    .Done()
    .Build();
// Or:
// .Save("out.pdf");
// .SaveEncrypted("out.pdf", "user-pw", "owner-pw");     // AES-256
// .ToBytesEncrypted("user-pw", "owner-pw");

HTML + CSS パイプライン

using var pdf = Pdf.FromHtmlCss(html, css, fontBytes);
using var pdf = Pdf.FromHtmlCssWithFonts(html, css, new[] {
    ("DejaVu Sans", font1),
    ("Noto Sans CJK", font2),
});

署名検証

using var doc = PdfDocument.Open("signed.pdf");

foreach (var sig in doc.Signatures)
{
    Console.WriteLine(sig.SignerName);
    Console.WriteLine(sig.Reason);
    Console.WriteLine(sig.Location);
    Console.WriteLine(sig.SigningTime);       // DateTimeOffset?

    SignatureStatus status = sig.Verify();    // Valid / Invalid / Unknown
    bool ok = sig.VerifyDetached(pdfBytes);

    using var cert = sig.GetCertificate();
    Console.WriteLine($"{cert.Subject} / {cert.Issuer} / {cert.Serial}");
    Console.WriteLine($"valid {cert.NotBefore} → {cert.NotAfter} (is_valid={cert.IsValid})");
}

var ts = Timestamp.Parse(tstBytes);
Console.WriteLine($"{ts.Time} serial={ts.Serial} tsa={ts.TsaName}");

var client = new TsaClient(
    url: "https://freetsa.org/tsr",
    username: null, password: null,
    timeoutSeconds: 30, hashAlgorithm: 2,
    useNonce: true, certReq: true);
var fresh = client.RequestTimestamp(pdfBytes);

SignatureStatus: ValidInvalidUnknown。RSA-PSS / ECDSA は Unknown を返し、厳格系メソッドではサポート外アルゴリズムが UnsupportedFeatureException を投げます。

レンダリング

byte[] region = doc.RenderPageRegion(pageIndex: 0, x: 72, y: 200, width: 468, height: 300, format: RenderFormat.Png);
byte[] fitted = doc.RenderPageFit(pageIndex: 0, fitWidth: 1024, fitHeight: 768, format: RenderFormat.Png);