Zum Inhalt springen

Guide · Python

PDFs zusammenfügen und mit Passwort schützen mit Python

Rechnung, AGB und Datenblatt sollen den Kunden als eine Datei erreichen, und sie soll nicht für jeden lesbar sein, der sie findet. Dieses Python-Programm verbindet bereits gerenderte Dokumente und verschlüsselt das Ergebnis, in zwei Aufrufen und ohne PDF-Bibliothek.

Kostenloser Plan mit 100 Einheiten im Monat, keine Kreditkarte

Was Sie brauchen

  • Einen API-Key. Legen Sie ihn in der App unter API-Schlüssel an und exportieren Sie ihn als FORMFEED_API_KEY. Zum Ausprobieren ist ein Test-Key (ff_test_…) richtig. Siehe Quickstart.
  • Python. Sie brauchen Python 3.10 oder neuer und das Paket formfeed (es bringt httpx und pydantic mit).
  • Die Quellen. sources.json neben dem Programm: ein JSON-Array dessen, was in das Dokument kommt, in dieser Reihenfolge. Eine Render-ID (rnd_…) oder der Name eines PDFs in der Workspace-Bibliothek, zwei bis fünfzig davon.
  • Ein Passwort. In FORMFEED_PDF_PASSWORD. Erzeugen Sie eines je Dokument und senden Sie es über einen anderen Kanal als die Datei.
  • Einen Tarif mit PDF-Tools. Die Tools gehören zu Starter und darüber.
InstallierenShell
pip install formfeed

Das Programm

Das Programm liest die Quellen, fügt sie zu einem PDF zusammen, verschlüsselt das Ergebnis mit dem Passwort und speichert die fertige Datei.

bundle.pyPython
import json
import os
from pathlib import Path

from formfeed import Formfeed

formfeed = Formfeed(api_key=os.environ["FORMFEED_API_KEY"])
sources = json.loads(Path("sources.json").read_text(encoding="utf-8"))

# 1. join the documents, in the order they are given
merged = formfeed.pdf.merge(sources, filename="bundle.pdf")

# 2. encrypt the result; printing stays allowed, copying and editing do not
protected = formfeed.pdf.protect(
    merged,
    user_password=os.environ["FORMFEED_PDF_PASSWORD"],
    permissions=["print"],
)

Path("bundle.pdf").write_bytes(formfeed.renders.download(protected))
print(protected.id, protected.page_count, "page(s),", protected.units, "unit(s)")

Ausführen

Es gibt die ID des Renderings, die Seitenzahl und die Einheiten aus, und bundle.pdf liegt neben dem Programm. Beim Öffnen fragt es nach dem Passwort; Drucken geht, Text kopieren nicht.

Shell
export FORMFEED_API_KEY=ff_test_...
export FORMFEED_PDF_PASSWORD=$(openssl rand -base64 18)
python bundle.py

Was an Python besonders ist

  • Keyword-Argumente. Jedes Feld der Anfrage ist ein Keyword-Argument (renders.create, pdf.protect), nach den Einträgen von renders.batch und den Quellen von pdf.merge, die zuerst kommen; verschachtelte Optionen wie settings oder post sind einfache Dictionaries.
  • Retries sind eingebaut. Der Client sendet mit jedem Rendering einen Idempotency-Key und wiederholt 429, 503 und Netzwerkfehler bis zu dreimal mit Backoff, mit demselben Schlüssel: Ein Retry einer Anfrage, die schon beantwortet wurde, erhält diese Antwort zurück statt eines zweiten Renderings.
  • Typisierte Ergebnisse. Die Antwort ist ein pydantic-Modell: render.download_url, render.page_count und render.units sind Attribute, keine Dictionary-Schlüssel.
  • Auch asynchron. AsyncFormfeed hat dieselben Methoden als Coroutinen, für FastAPI oder jeden anderen asyncio-Dienst.

Warum zwei Aufrufe

  • Die Reihenfolge zählt. Ein verschlüsseltes PDF lässt sich nicht mehr ändern, das Passwort kommt also zuletzt. Ein bereits geschütztes Dokument zusammenzufügen scheitert.
  • Jeder Schritt ist ein Rendering. Zusammenfügen und Schützen erzeugen je ein eigenes Rendering mit ID, Download-URL und Zeile im Render-Log; das zweite nimmt die ID des ersten als Quelle.
  • Je eine halbe Einheit. Ein Tool kostet mit einem Live-Schlüssel 0,5 Einheiten, unabhängig von der Seitenzahl. Die Renderings, die die Quellen erzeugt haben, wurden gezählt, als sie liefen.
  • Oder in einer Anfrage. Ein Rendering kann dieselben Schritte als post mitbringen und alles in einem Aufruf erledigen. Nehmen Sie die Tools, wenn die Dokumente schon da sind, und post, wenn Sie ohnehin rendern. Siehe PDF-Tools.

Was die Berechtigungen tun

Alles, was nicht in permissions steht, ist verboten (fehlt die Liste, sind alle vier erlaubt: print, copy, modify und annotate): Mit ["print"] darf gedruckt, aber kein Text kopiert, bearbeitet oder kommentiert werden. Ohne user_password kann jeder das Dokument öffnen, und die Berechtigungen gelten trotzdem; das ist die richtige Einstellung für ein Dokument, das öffentlich ist, aber nicht bearbeitet werden soll. Ein owner_password hebt die Beschränkungen auf; ohne Angabe wird ein zufälliges verwendet. PDF-Viewer beachten die Berechtigungen, sie schützen aber nicht vor jemandem, der die Datei öffnen kann: Vertraulich macht sie erst das user_password.

Wenn die API nein sagt

  • Eine Form für jeden Fehler. Fehler sind Problem-Dokumente (RFC 9457) mit type, title, status, detail, einem stabilen code und der request_id, die Sie dem Support nennen; die type-URL führt zu einer Seite über diesen Fehler. Die Liste steht in der Fehlerreferenz.
  • Die üblichen. 401 unauthorized bei fehlendem oder widerrufenem Schlüssel, 404 template_not_found bei falschem Vorlagennamen, 422 template_runtime_error, wenn die Vorlage an den Daten scheitert, 429 rate_limited über den Anfragen pro Sekunde des Tarifs, 402 quota_exceeded, wenn die Einheiten des Free-Tarifs verbraucht sind (ein bezahlter Tarif rechnet weitere Einheiten ab, bis zu seiner Obergrenze).
  • Sicher wiederholen. Senden Sie beim POST einen Idempotency-Key-Header und wiederholen Sie die Anfrage mit demselben Schlüssel, wenn Sie nicht wissen, ob der erste Versuch ankam: 24 Stunden lang liefert der Schlüssel die erste Antwort, statt erneut zu rendern und zu berechnen. Gespeichert wird die Antwort, sobald der erste Versuch beantwortet ist; wiederholen Sie also nicht, solange er noch laufen kann. Auch Probleme unter 500 werden gespeichert, eine korrigierte Anfrage braucht deshalb einen neuen Schlüssel.

Die Aufgabe um dieses Programm

Dieser Guide ist ein Programm. Was die Aufgabe darum herum braucht, von der Vorlage bis zu Limits und Preis, steht auf der Seite Verträge und Vereinbarungen als PDF.

Weitere Guides für Python

FAQ

Woher kommen die Render-IDs?
Aus den Renderings, die Sie vorher gemacht haben: die id jeder Antwort. Sie müssen zum selben Workspace gehören, und ihre Ausgabe muss noch existieren. Dateien, die Sie in die Bibliothek geladen haben, nennen Sie stattdessen beim Namen.
Welche Verschlüsselung wird verwendet?
AES-256, ausgeführt von qpdf. Das Passwort erscheint nie im Render-Log und wird nicht gespeichert: Geht es verloren, lässt sich das Dokument nicht mehr öffnen.
Kann ich auch ein Wasserzeichen setzen?
Ja, /pdf/watermark ist das dritte Tool und nimmt einen Text oder ein Bild. Hängen Sie es vor das Passwort, wie das Zusammenfügen. Siehe PDF-Tools.

Zusammenfügen und schützen in anderen Sprachen

Heute mit dem Rendern beginnen

Der kostenlose Plan enthält 100 Einheiten im Monat und kostenlose Testrenderings. Wechseln Sie den Plan, wenn Sie mehr brauchen.