Dokumentenverwaltung

Dokumentenverwaltung

Dokumentenverwaltung

Die Document-Klasse ist der Einstiegspunkt für fast jede Operation in Aspose.PDF FOSS für Python: ein neues PDF erstellen, ein bestehendes laden, seine Seiten bearbeiten und das Ergebnis wieder schreiben. Dieser Leitfaden führt durch den Dokumentenlebenszyklus, Operationen zur Seitensammlung, Optimierung, Mehrdatei-Workflows, Verschlüsselung und die Ausnahmen, die Sie erwarten sollten zu behandeln.


Dokumentenlebenszyklus: Erstellen, Öffnen und Speichern

Document() erzeugt ohne Argumente ein leeres, im Speicher befindliches Dokument. Übergeben Sie einen Dateipfad, rohes bytes oder irgendeinen lesbaren Binärstrom als erstes Argument (oder rufen Sie load_from() explizit auf), um stattdessen ein vorhandenes PDF zu laden. save() akzeptiert einen Pfad oder einen beschreibbaren Binärstrom wie io.BytesIO.

from aspose_pdf import Document

# Create a new, empty document and add a blank page
doc = Document()
doc.pages.add()
doc.save("hello.pdf")

# Re-open it — a path, bytes, or a binary stream all work
reopened = Document("hello.pdf")
print(reopened.page_count)   # 1

# ...or load explicitly onto an existing instance
another = Document()
another.load_from("hello.pdf")

reopened.close()
another.dispose()
doc.dispose()

save() wirft FileExistsError, wenn der Zielpfad bereits existiert, es sei denn, Sie übergeben overwrite=True. close() ist ein Alias für dispose(); beide sind idempotent, sodass ein mehrfacher Aufruf sicher ist.

Nur PDF ist als Speicherziel implementiert — dies ist der Kern der Bibliothek, eine voll funktionsfähige Funktion. Das Übergeben eines Exportwerts wie SaveFormat.PPTX oder DocFormat.HTML an save() löst UnsupportedFeatureException aus, anstatt eine falsch benannte Datei zu schreiben, sodass ein fehlgeschlagener Export immer laut und nicht still ist.


Verwalten der Seitensammlung

doc.pages ist ein PageCollection. Es unterstützt len(), Iteration und 0-basierte Indizierung (doc.pages[0]), sowie add(), insert(index, page) und delete(index) für strukturelle Bearbeitungen. Jede Page stellt index, rect (das MediaBox) und rotation bereit.

from aspose_pdf import Document

doc = Document()
doc.pages.add()            # page 0
doc.pages.add()            # page 1
doc.pages.insert(1, None)  # insert a blank page at index 1

print(doc.page_count)      # 3

first_page = doc.pages[0]
print(first_page.rect)     # (0, 0, 612, 792)

for page in doc.pages:
    print(page.index, page.rotation)

doc.pages.delete(1)        # remove the page we inserted
doc.save("pages_demo.pdf", overwrite=True)

pages.add(page=None) fügt eine leere Seite hinzu, wenn es ohne Argument aufgerufen wird. pages.insert() begrenzt einen Index außerhalb des gültigen Bereichs auf die nächstgelegene gültige Position, anstatt einen Fehler zu werfen.


Optimieren und Komprimieren von Dokumenten

Document.optimize führt Bild-/Stream-Deduplizierung, Garbage Collection ungenutzter Objekte und Stream-Kompression in einem Aufruf aus. Übergeben Sie eine OptimizationOptions-Instanz, um zu steuern, welche Techniken ausgeführt werden; lassen Sie sie weg, um das Standard-Bereinigungsprofil zu verwenden.

from aspose_pdf import Document, OptimizationOptions

doc = Document("large_report.pdf")

options = OptimizationOptions()
options.remove_unused_objects = True
options.link_duplicate_streams = True
options.image_compression_quality = 60
options.subset_fonts = True

doc.optimize(options)
doc.save("large_report_optimized.pdf", overwrite=True)

optimize_resources() ist ein Alias für optimize(). Wenn Sie nur die Stream-Kompression ohne den strukturellen Bereinigungsschritt wünschen, rufen Sie doc.compress_streams() direkt auf.


Zusammenführen, Aufteilen und Bearbeiten von Dateien

Für bereits geöffnete Dokumente fügt Document.merge() andere Document-Instanzen an das aktuelle an:

from aspose_pdf import Document

base = Document("part1.pdf")
extra = Document("part2.pdf")

base.merge(extra)
base.save("combined.pdf", overwrite=True)

Für Datei-zu-Datei-Workflows, bei denen Sie kein Document selbst öffnen, übernehmen die Low-Code-Plugins Merger und Splitter ein aus FileDataSource Eingaben und Ausgaben erstelltes MergeOptions/SplitOptions-Objekt:

from aspose_pdf import Merger, MergeOptions, Splitter, SplitOptions, FileDataSource

# Merge two files into one
merge_options = MergeOptions()
merge_options.add_input(FileDataSource("part1.pdf"))
merge_options.add_input(FileDataSource("part2.pdf"))
merge_options.add_output(FileDataSource("combined.pdf"))
Merger().process(merge_options)

# Split the result into one file per page
split_options = SplitOptions()
split_options.add_input(FileDataSource("combined.pdf"))
split_options.add_output(FileDataSource("combined_page1.pdf"))
split_options.add_output(FileDataSource("combined_page2.pdf"))
Splitter().process(split_options)

PdfFileEditor bietet dieselbe Familie von Operationen als Fassade, die True/False zurückgibt, anstatt eine Ausnahme zu werfen, was für Batch-Skripte praktisch ist:

from aspose_pdf import PdfFileEditor

with PdfFileEditor() as editor:
    ok = editor.concatenate(["part1.pdf", "part2.pdf"], "combined.pdf")
    if not ok:
        print("concatenate failed:", editor.last_exception)

    editor.extract("combined.pdf", "first_page_only.pdf", page_from=1, page_to=1)

PdfFileEditor.extract() and .insert() take 1-basiert Seitenzahlen, im Gegensatz zu PageCollection’s 0-basierte Indizierung — siehe Häufige Probleme unten.


Verschlüsselung und Dokumentensicherheit

Document.encrypt(user_password, owner_password=None, permissions=-4) verschlüsselt das Dokument im Speicher; decrypt(password) und change_passwords(old, new_user, new_owner=None) kehren Passwörter um oder rotieren sie. is_encrypted und permissions geben den aktuellen Zustand zurück.

from aspose_pdf import Document
from aspose_pdf.exceptions import PdfSecurityException

doc = Document()
doc.pages.add()
doc.encrypt("user-pass", "owner-pass", permissions=-4)
doc.save("secured.pdf", overwrite=True)

try:
    Document("secured.pdf", password="wrong-pass")
except PdfSecurityException as exc:
    print("could not open:", exc)

reopened = Document("secured.pdf", password="user-pass")
print(reopened.is_encrypted)   # True
reopened.decrypt("user-pass")
reopened.save("unsecured.pdf", overwrite=True)

Das Öffnen eines verschlüsselten Dokuments ohne Passwort oder mit falschem Passwort löst PdfSecurityException aus — fange diese Klasse (aus aspose_pdf.exceptions) ab, anstatt anzunehmen, dass ein Ladevorgang immer erfolgreich ist.


Metadaten, Validierung und Ausnahmebehandlung

Dokumentmetadaten befinden sich auf doc.info (ein einfaches dict[str, str]), und doc.version / doc.id geben die PDF-Header-Version und die Trailer-Datei-Kennung frei. validate() (alias check()) meldet die strukturelle Integrität; repair() versucht, gängige Probleme zu beheben, wie eine fehlende Seitenliste oder ein MediaBox außerhalb des Bereichs.

from aspose_pdf import Document, PdfLoadLimits
from aspose_pdf.exceptions import AsposePdfException, PdfIOException

doc = Document()
doc.pages.add()
doc.info["Title"] = "Quarterly Report"
doc.info["Author"] = "Reporting Bot"
doc.save("report.pdf", overwrite=True)

# Load untrusted input under an explicit resource-limit policy
safe_limits = PdfLoadLimits(max_input_bytes=50 * 1024 * 1024, max_pages=1000)

try:
    untrusted = Document("incoming.pdf", limits=safe_limits)
    if not untrusted.validate():
        untrusted.repair()
except (AsposePdfException, PdfIOException) as exc:
    print("failed to process incoming.pdf:", exc)

PdfLoadLimits begrenzt Speicher- und Objektzahlen für nicht vertrauenswürdige Dateien; rufe PdfLoadLimits.unlimited() auf, um alle Beschränkungen zu deaktivieren, wenn du die Quelle vollständig vertraust. AsposePdfException ist die Basisklasse für die gesamte Ausnahme-Hierarchie (einschließlich PdfIOException und PdfSecurityException), sodass ein einzelnes except AsposePdfException jede von der Bibliothek ausgelöste Fehlermeldung abfängt.


Tipps und bewährte Verfahren

  • Rufen Sie immer dispose() (oder close()) auf einem Document auf, wenn Sie damit fertig sind, oder verwenden Sie es als kurzlebige lokale Variable — die Engine hält dekodierten Seiteninhalt und Bilder im Speicher, bis sie verworfen werden.
  • Übergeben Sie overwrite=True an save(), wenn Sie einen Pfad neu schreiben, den Sie bereits im selben Durchlauf erstellt haben; der Standardwert ist False und löst FileExistsError aus.
  • Bevorzugen Sie doc.optimize() vor dem Ausliefern eines erzeugten PDFs — es ist ein einzelner Aufruf, der ungenutzte Objekte entfernt und Streams komprimiert und in der Regel die Ausgabengröße deutlich reduziert.
  • Legen Sie eine PdfLoadLimits-Richtlinie ausdrücklich fest, wann immer Sie PDFs aus einer nicht vertrauenswürdigen Quelle laden (Uploads, E-Mail-Anhänge, Web-Scrapes); die Vorgaben sind großzügig, aber endlich und keine Sicherheitsgrenze, auf die Sie blind vertrauen sollten.
  • Fangen Sie AsposePdfException (oder eine spezifische Unterklasse wie PdfSecurityException) um Lade-/Speicheraufrufe herum, anstatt bloßes Exception — es ist die gemeinsame Basis für jeden Fehler, den die Bibliothek auslöst.

Häufige Probleme

ProblemUrsacheLösung
FileExistsError auf save()Zielpfad existiert bereits und overwrite wurde bei seinem Standard-False belassenDurchlauf save(path, overwrite=True)
UnsupportedFeatureException auf save()Ein nicht-PDF save_format (z.B. SaveFormat.PPTX, DocFormat.HTML) wurde angefordertAls PDF speichern — jeder andere SaveFormat/DocFormat-Wert löst UnsupportedFeatureException aus, anstatt die Ausgabe zu schreiben
PdfSecurityException: Password required for encrypted documentEin verschlüsseltes PDF wurde ohne ein password-Argument geöffnetÜbergebe Document(path, password="...") oder rufe load_from(path, password="...") auf
Off-by-one-Seitenzahlen zwischen PageCollection und PdfFileEditordoc.pages[i] ist 0-basiert; PdfFileEditor.extract()/.insert() Seitenargumente sind 1-basiertAddiere oder subtrahiere 1 beim Konvertieren zwischen den beiden APIs
IndexError: Page index out of range. von pages.delete()Der an delete() übergebene Index existiert nicht in der SammlungÜberprüfe doc.page_count (oder len(doc.pages)) vor dem Löschen

FAQ

Benötige ich eine Lizenz, um Aspose.PDF FOSS für Python zu verwenden?

Nein. Dies ist die Open-Source-Ausgabe (MIT-lizenzierte); es gibt keine Lizenzdatei oder Aktivierungsschritt zum Konfigurieren.

Kann ich ein Document in andere Formate als PDF exportieren?

Nicht in dieser Version. save() unterstützt nur die PDF-Ausgabe — das Übergeben eines anderen SaveFormat/DocFormat-Werts löst UnsupportedFeatureException aus, anstatt eine falsch benannte Datei zu erzeugen.

Was ist der Unterschied zwischen Document.merge() und dem Merger-Plugin?

Document.merge() kombiniert Document-Instanzen, die Sie bereits im Speicher geöffnet haben. Merger (mit MergeOptions und FileDataSource) ist ein Datei-zu-Datei-Bequemlichkeits-Wrapper, der für Sie in einem Aufruf öffnet, zusammenführt und speichert — nützlich für einfache Batch-Skripte, die niemals das Zwischenergebnis-Objekt Document benötigen.

Warum löst pages.insert() nie einen Fehler bei einem Index außerhalb des gültigen Bereichs aus?

PageCollection.insert() begrenzt den Index auf den gültigen Bereich (negative Werte werden zu 0, Werte jenseits des Endes werden zu len(doc.pages)), anstatt einen Fehler auszulösen, sodass ein Einfügen nie rein wegen des Indexwertes scheitert.

Wie lade ich ein PDF aus einer nicht vertrauenswürdigen Quelle sicher?

Erstelle ein PdfLoadLimits mit expliziten Obergrenzen (max_input_bytes, max_pages, max_objects usw.) und übergebe es als limits=-Argument an Document(...) oder load_from(). Jedes Feld hat bereits einen endlichen Standardwert, aber das Einschränken auf die erwartete Eingabegröße reduziert die Ressourcen, die eine fehlerhafte Datei verbrauchen kann.


API Reference Zusammenfassung

Klasse / MethodeBeschreibung
Document() / Document.load_fromErstellen Sie ein leeres Dokument oder laden Sie eines aus einem Pfad, Bytes oder einem Binär-Stream
Document.saveSchreiben Sie das Dokument in einen Pfad oder in einen schreibbaren Stream (nur PDF)
Document.dispose() / Document.close()Geben Sie Engine-Ressourcen frei; idempotent
Document.pagesDas PageCollection des Dokuments
Document.infoDokumentmetadaten als dict[str, str]
Document.optimize / Document.optimize_resources / Document.compress_streams()Nicht verwendete Ressourcen entfernen und Streams komprimieren
Document.merge()Weitere Document-Instanzen an diese anhängen
Document.encrypt / Document.decrypt / Document.change_passwordsDokumentpasswörter anwenden, entfernen oder rotieren
Document.validate() / Document.check() / Document.repair()Überprüfen und versuchen, die strukturelle Integrität zu reparieren
PageCollection.add() / .insert() / .delete() / .item()Strukturelle Seiten-Sammlungs-Änderungen (0-basiert)
Page.rect / Page.rotation / Page.indexGeometrie und Position pro Seite
OptimizationOptionsFein granulare Flags, die von Document.optimize verwendet werden
MergeOptions / MergerDatei-zu-Datei-Merge-Plugin
SplitOptions / SplitterDatei-zu-Datei Ein-Seite-pro-Ausgabe Split-Plugin
FileDataSourceDateibasiertes Ein-/Ausgabe für die Plugin-APIs
PdfFileEditorFassade für concatenate(), extract(), insert(), delete(), append() (1-basierte Seiten)
PdfLoadLimitsUnveränderliche Ressourcen-Limit-Richtlinie für nicht vertrauenswürdige Eingabe
AsposePdfExceptionBasisklasse für jede Ausnahme, die die Bibliothek wirft
PdfSecurityExceptionAusgelöst bei fehlenden/inkorrekten Passwörtern und Berechtigungsfehlern
PdfIOExceptionAusgelöst bei Ein-/Ausgabe-Fehlern während der PDF-Verarbeitung

Siehe auch

 Deutsch