Guide · Ruby
PDFs zusammenfügen und mit Passwort schützen mit Ruby
Rechnung, AGB und Datenblatt sollen den Kunden als eine Datei erreichen, und sie soll nicht für jeden lesbar sein, der sie findet. Dieses Ruby-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. - Ruby. Sie brauchen Ruby 3; das Programm nutzt
net/httpundjsonaus der Standardbibliothek. - Die Quellen.
sources.jsonneben 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.
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.
require "json"
require "net/http"
BASE = URI("https://api-eu.formfeed.dev/v1/")
def api(path, body)
uri = URI.join(BASE, path)
response = Net::HTTP.post(
uri,
JSON.generate(body),
"Authorization" => "Bearer #{ENV.fetch("FORMFEED_API_KEY")}",
"Content-Type" => "application/json"
)
answer = JSON.parse(response.body)
abort "#{answer["title"]}: #{answer["detail"]}" unless response.is_a?(Net::HTTPSuccess)
answer
end
sources = JSON.parse(File.read("sources.json"))
# 1. join the documents, in the order they are given
merged = api("pdf/merge", { sources: sources, filename: "bundle.pdf" })
# 2. encrypt the result; printing stays allowed, copying and editing do not
protected_pdf = api("pdf/protect", {
source: merged["id"],
user_password: ENV.fetch("FORMFEED_PDF_PASSWORD"),
permissions: ["print"]
})
File.binwrite("bundle.pdf", Net::HTTP.get(URI(protected_pdf["download_url"])))
puts "#{protected_pdf["id"]} #{protected_pdf["page_count"]} page(s), #{protected_pdf["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.
export FORMFEED_API_KEY=ff_test_...
export FORMFEED_PDF_PASSWORD=$(openssl rand -base64 18)
ruby bundle.rbWas an Ruby besonders ist
- Hashes werden zu JSON. Symbol-Keys sind in Ordnung:
JSON.generateschreibt sie als Strings, und die snake_case-Namen der API sind ohnehin idiomatisches Ruby. abortmit dem Problem. Ein Problem-Dokument enthälttitleunddetail; das Programm gibt beides aus und endet mit Status 1.- In Rails. Legen Sie den Aufruf in einen Job (Active Job, Sidekiq), nicht in den Request-Zyklus: Ein synchrones Rendering antwortet, wenn das PDF fertig ist, und das kann bis zu 60 Sekunden dauern, bevor die API mit
202antwortet und im Hintergrund fertig rendert.
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
postmitbringen und alles in einem Aufruf erledigen. Nehmen Sie die Tools, wenn die Dokumente schon da sind, undpost, 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 stabilencodeund derrequest_id, die Sie dem Support nennen; dietype-URL führt zu einer Seite über diesen Fehler. Die Liste steht in der Fehlerreferenz. - Die üblichen.
401 unauthorizedbei fehlendem oder widerrufenem Schlüssel,404 template_not_foundbei 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 Ruby
FAQ
- Woher kommen die Render-IDs?
- Aus den Renderings, die Sie vorher gemacht haben: die
idjeder 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/watermarkist das dritte Tool und nimmt einen Text oder ein Bild. Hängen Sie es vor das Passwort, wie das Zusammenfügen. Siehe PDF-Tools.