Skip to content

Erste Schritte mit PDF Oxide (Dart / Flutter)

PDF Oxide ist der schnellste Weg, PDFs aus Dart und Flutter zu lesen — 0,8 ms mittlere Textextraktion, 100 % Erfolgsquote bei 3.830 PDFs. Das Paket pdf_oxide ist ein idiomatischer dart:ffi-Wrapper über dem Rust-Kern: PDF-Handles werden automatisch durch einen NativeFinalizer (und durch explizites close()) freigegeben, C-Strings und Puffer werden für Sie nach Dart kopiert, und C-ABI-Fehlercodes treten als PdfOxideError-Exception in Erscheinung.

Installation

Fügen Sie pdf_oxide zu Ihrer pubspec.yaml hinzu:

dependencies:
  pdf_oxide: ^0.3.69

Holen Sie anschließend die Abhängigkeiten:

dart pub get

Das Binding lädt die native Bibliothek (libpdf_oxide.{so,dylib,dll}) zur Laufzeit. Die Auflösungsreihenfolge ist PDF_OXIDE_LIB_PATH (vollständiger Pfad) → PDF_OXIDE_LIB_DIR../target/releasetarget/release → der System-Loader. Liefern Sie bei Flutter die Plattform-Bibliothek mit Ihrer App aus und verweisen Sie mit PDF_OXIDE_LIB_PATH darauf.

Schnellstart

Öffnen Sie ein PDF und holen Sie den Text der ersten Seite ab. Rufen Sie immer close() für das Dokument auf, wenn Sie fertig sind — try/finally hält das sauber.

import 'package:pdf_oxide/pdf_oxide.dart';

void main() {
  final doc = PdfDocument.open('research-paper.pdf');
  try {
    print('Pages: ${doc.pageCount}');
    print('PDF version: ${doc.version}'); // e.g. 1.7
    print(doc.extractText(0));
  } finally {
    doc.close();
  }
}

Um ein PDF zu öffnen, das sich bereits im Speicher befindet (zum Beispiel über HTTP heruntergeladen in einer Flutter-App), verwenden Sie openFromBytes:

import 'dart:typed_data';
import 'package:pdf_oxide/pdf_oxide.dart';

void render(Uint8List bytes) {
  final doc = PdfDocument.openFromBytes(bytes);
  try {
    print(doc.extractText(0));
  } finally {
    doc.close();
  }
}

Text, Markdown und HTML

Jede Seite kann als reiner Text, Markdown oder HTML gerendert werden. Die Methoden pro Seite erwarten einen 0-basierten Seitenindex; die …All()-Varianten laufen über das gesamte Dokument.

import 'package:pdf_oxide/pdf_oxide.dart';

void main() {
  final doc = PdfDocument.open('report.pdf');
  try {
    // Single page (index 0)
    print(doc.extractText(0));   // raw extracted text
    print(doc.toPlainText(0));   // normalized plain text
    print(doc.toMarkdown(0));    // Markdown with headings, lists, tables
    print(doc.toHtml(0));        // HTML

    // Whole document
    print(doc.toMarkdownAll());
    print(doc.toHtmlAll());
    print(doc.toPlainTextAll());
  } finally {
    doc.close();
  }
}

Es gibt außerdem eine leichtgewichtige Page-Ansicht, falls Sie lieber Seite für Seite arbeiten:

final doc = PdfDocument.open('report.pdf');
final page = doc.page(0);
print(page.text());
print(page.markdown());
doc.close();

Wörter und Zeilen mit Koordinaten

extractWords liefert jedes Wort mit seinem Begrenzungsrahmen, seiner Schriftart und seinem Schriftschnitt; extractTextLines liefert ganze Zeilen. Die Koordinaten sind in PDF-Benutzerraum-Punkten angegeben.

import 'package:pdf_oxide/pdf_oxide.dart';

void main() {
  final doc = PdfDocument.open('paper.pdf');
  try {
    for (final word in doc.extractWords(0)) {
      final b = word.bbox; // Bbox(x, y, width, height)
      print("'${word.text}' at (${b.x}, ${b.y}) "
          'font=${word.fontName} size=${word.fontSize} bold=${word.bold}');
    }

    for (final line in doc.extractTextLines(0)) {
      print('${line.wordCount} words: ${line.text}');
    }
  } finally {
    doc.close();
  }
}

Für Details auf Glyphenebene liefert extractChars jedes Char mit seinem Unicode-Codepoint, seinem Begrenzungsrahmen, seinem Schriftartnamen und seiner Größe:

final doc = PdfDocument.open('paper.pdf');
for (final ch in doc.extractChars(0)) {
  print('${String.fromCharCode(ch.character)} @ ${ch.bbox} ${ch.fontSize}pt');
}
doc.close();

Suche

search sucht innerhalb einer einzelnen Seite; searchAll durchsucht das gesamte Dokument. Beide erwarten einen Suchbegriff und ein caseSensitive-Flag und liefern SearchResult-Records, die den gefundenen Text, seinen Seitenindex und seinen Begrenzungsrahmen tragen.

import 'package:pdf_oxide/pdf_oxide.dart';

void main() {
  final doc = PdfDocument.open('manual.pdf');
  try {
    // Single page (page 0), case-insensitive
    for (final hit in doc.search(0, 'configuration', false)) {
      print("page ${hit.page}: '${hit.text}' at ${hit.bbox}");
    }

    // Across the whole document
    final hits = doc.searchAll('configuration', false);
    print('${hits.length} matches');
  } finally {
    doc.close();
  }
}

Ein PDF erstellen

Der Pdf-Builder verwandelt Markdown, HTML oder reinen Text in ein PDF. Rufen Sie toBytes() auf, um die Bytes zu erhalten, oder save(), um eine Datei zu schreiben, und close(), wenn Sie fertig sind.

import 'package:pdf_oxide/pdf_oxide.dart';

void main() {
  final pdf = Pdf.fromMarkdown('# Hello World\n\nThis is a **PDF**.\n');
  try {
    pdf.save('output.pdf');
    final bytes = pdf.toBytes();
    print('Wrote ${bytes.length} bytes');
  } finally {
    pdf.close();
  }
}

Pdf.fromHtml('<h1>Invoice</h1><p>Amount: \$42</p>') und Pdf.fromText('Plain text content.') funktionieren auf dieselbe Weise. Da ein erstelltes Pdf einfach nur Bytes ist, können Sie es direkt an PdfDocument.openFromBytes(pdf.toBytes()) weitergeben, um es wieder zu extrahieren, ohne die Festplatte zu berühren.

Fehlerbehandlung

Jeder fehleranfällige Aufruf wirft PdfOxideError (was implements Exception) und trägt den zugrunde liegenden C-ABI-Fehlercode:

import 'package:pdf_oxide/pdf_oxide.dart';

void main() {
  try {
    final doc = PdfDocument.open('/nonexistent/nope.pdf');
    doc.close();
  } on PdfOxideError catch (e) {
    print('Failed to open PDF: $e');
  }
}

Nächste Schritte