Zum Inhalt springen

Guide · Node.js (TypeScript)

PDFs zusammenfügen und mit Passwort schützen mit Node.js (TypeScript)

Rechnung, AGB und Datenblatt sollen den Kunden als eine Datei erreichen, und sie soll nicht für jeden lesbar sein, der sie findet. Dieses Node.js (TypeScript)-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.
  • Node.js (TypeScript). Sie brauchen Node.js 22 oder neuer und das Paket @formfeed/sdk, das selbst keine Abhängigkeiten hat.
  • 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
npm install @formfeed/sdk
npm install --save-dev tsx   # führt die .ts-Datei direkt aus

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.tsTypeScript
import { readFile, writeFile } from 'node:fs/promises';
import { Formfeed } from '@formfeed/sdk';

const formfeed = new Formfeed({ apiKey: process.env.FORMFEED_API_KEY! });
const sources: string[] = JSON.parse(await readFile('sources.json', 'utf8'));

// 1. join the documents, in the order they are given
const merged = await formfeed.pdf.merge(sources, { filename: 'bundle.pdf' });

// 2. encrypt the result; printing stays allowed, copying and editing do not
const protectedPdf = await formfeed.pdf.protect(merged, {
  user_password: process.env.FORMFEED_PDF_PASSWORD!,
  permissions: ['print'],
});

await writeFile('bundle.pdf', await formfeed.renders.download(protectedPdf));
console.log(protectedPdf.id, protectedPdf.page_count, 'page(s),', protectedPdf.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)
npx tsx bundle.ts

Was an Node.js (TypeScript) besonders ist

  • Top-Level-await. Die Datei verwendet await außerhalb einer Funktion, sie muss also ein ES-Modul sein: "type": "module" in der package.json oder die Endung .mts.
  • Retries sind eingebaut. Das SDK 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 Fehler. Eine Problem-Antwort wirft einen FormfeedError, dessen code der Fehlercode der API ist (template_not_found, quota_exceeded, …); fangen Sie ihn dort, wo Sie dem Nutzer etwas Sinnvolles zeigen können.
  • Läuft überall, wo es fetch gibt. Das SDK nutzt nur Web-APIs, derselbe Aufruf funktioniert also in Deno, Bun und Cloudflare Workers; nur der Dateizugriff ist anders.

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 Node.js (TypeScript)

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.