Der monatliche Kontoauszugslauf sah auf jedem Entwicklerbildschirm sauber aus, also wurde er ausgeliefert. Die Druckerei gab zwei Tage später den gesamten Stapel zurück: RGB-Bilder in einem CMYK-Auftrag und keine /Trapped-Deklaration. Der eigentliche Preis war nicht der Neudruck, sondern zwei verlorene Tage vor einer regulatorischen Frist. „Preflight“ ist der Vorstufenbegriff für genau diese Problemklasse, bevor Dateien das Haus verlassen. Die interessante Engineering-Frage für ein Delphi-Team ist, wo diese Prüfung hingehört, wenn die PDFs nicht von Desktop-Werkzeugen eines Designers stammen, sondern vom eigenen Code mit einer Bibliothek wie HotPDF erzeugt werden.
Vorbeugung schlägt Prüfung, wenn Ihnen der Generator gehört
Klassisches Preflight nimmt eine fremde Datei unbekannter Qualität an und untersucht sie nachträglich. Wenn Ihre eigene Anwendung das Dokument erzeugt, ist diese Architektur verkehrt herum: Jede Eigenschaft, die der Inspektor prüfen würde, Schrifteinbettung, Farbraumnutzung, Output Intents, Metadaten, wurde Millisekunden vorher von Ihrem Code entschieden. Der günstigste Preflight-Fehler ist der, der bereits bei der Generierung unmöglich gemacht wird.
Es lohnt sich, hier präzise zu sein, was HotPDF bietet und was nicht. Die Komponente liefert ein Preflight-Berichtsfenster als Teil der GUI-Demoanwendung, aber es gibt keine programmatische Preflight-API, die Sie aus einem Dienst oder Build-Skript aufrufen können. Das ist weniger Lücke, als es zunächst wirkt, denn für generierte Dokumente hat das robuste Muster ohnehin zwei unabhängige Hälften: Den Generator so einschränken, dass er keine nichtkonformen Strukturen ausgeben kann, und die Ausgabe anschließend mit einem Validator prüfen, den Sie nicht selbst pflegen. Eine Bibliothek, die ihre eigene Ausgabe validiert, bewertet ihre eigenen Hausaufgaben; ein externes Werkzeug liefert Belege, die ein Kunde oder Auditor akzeptiert.
Die Generierungsseite: Compliance als Konfiguration, nicht als Review-Punkt
Die Standard-Eigenschaften von HotPDF sind die Vorbeugungsschicht. Wenn PDFACompliance oder PDFXCompliance vor BeginDoc gesetzt wird, erzwingt die Komponente die jeweiligen Regeln während der Generierung: Schriften werden eingebettet, DeviceRGB- und DeviceCMYK-Nutzung gegen den deklarierten Output Intent verfolgt, und vom Profil verbotene Funktionen werden abgewiesen. Nach dem Speichern halten dieselben Eigenschaften fest, was erzwungen wurde, und genau das braucht Ihr Pipeline-Log:
// After EndDoc: record the enforced profiles with the run metadata
if Pdf.PDFACompliance <> '' then
Log('Generated as PDF/A level ' + Pdf.PDFACompliance);
if Pdf.PDFXCompliance <> '' then
Log('Generated as PDF/X profile ' + Pdf.PDFXCompliance);
Schreiben Sie diese Flags, den Hash der Eingabedaten und die HotPDF-Version in dieselbe Logzeile. Wenn ein Validator später dem Generator widerspricht, zeigt diese Zeile, welche Template-Revision und welche Bibliotheksversion die strittige Datei erzeugt hat, und eine einfache Logdisziplin ersetzt einen Nachmittag forensischen Ratens. Die vollständige Konfiguration hinter diesen Flags, Output Intents, ICC-Profilen und Tagging, wird in unserem Leitfaden zu PDF/A-, PDF/X- und PDF/UA-Ausgabe mit HotPDF behandelt.
Eingehende Dateien triagieren, bevor sie teure Prüfungen erreichen
Viele Pipelines sind nicht rein generativ: Kunden laden PDFs hoch, Scanner legen sie ab, Partner schicken sie per E-Mail. Eine vollständige Strukturvalidierung für jede eingehende Datei verschwendet Warteschlangenzeit auf Eingaben, die sich nicht einmal öffnen lassen. Die Direct File API von HotPDF liest Dateistrukturen, ohne den vollständigen Objektbaum zu laden, und eignet sich dadurch als günstiges erstes Gate:
function TriagePdf(Pdf: THotPDF; const FileName: string): Boolean;
var
Handle, Pages: Integer;
begin
Result := False;
Handle := Pdf.DAOpenFileReadOnly(FileName, '');
if Handle <= 0 then
Exit; // structurally unreadable: quarantine, do not validate
try
Pages := Pdf.DAGetPageCount(Handle);
Result := Pages > 0;
finally
Pdf.DACloseFile(Handle);
end;
end;
Zwei Verhaltensweisen dieser API prägen die umgebende Logik. DAOpenFileReadOnly bleibt nur bei unverschlüsselten Eingaben speicherflach — übergeben Sie ein Passwort, fällt der Aufruf intern auf einen vollständigen Parse zurück —, daher sollten bekannt verschlüsselte Dateien zuerst über DecryptFile in eine unverschlüsselte Arbeitskopie geführt werden. Außerdem ist DAGetPageCount nur für ein Handle aus einem erfolgreichen Öffnen gültig, daher sollte die Handle-Prüfung streng bleiben, statt einen positiven Wert anzunehmen. Weitere Muster für diese API stehen in dem Artikel zur Direct File API für große PDF-Workflows.
Die Verifikationsseite: veraPDF als Build-Schritt
Für PDF/A- und PDF/UA-Behauptungen ist veraPDF der Validator, der in die Pipeline gehört: Er läuft headless, verarbeitet Stapel, gibt maschinenlesbares XML oder JSON aus und meldet jeden Fehler mit ISO-Klauselnummer. Ein Befund wie ein Regelverstoß gegen ISO 19005-1 Klausel 6.2.2 lässt sich dadurch direkt einer bekannten Generator-Einstellung zuordnen. Der Aufruf aus Delphi ist gewöhnliche Prozesssteuerung:
function RunVeraPdf(const PdfFile, ReportFile: string): Cardinal;
var
Cmd: string;
SI: TStartupInfo;
PI: TProcessInformation;
begin
Cmd := Format('cmd /c verapdf.bat --format xml "%s" > "%s"',
[PdfFile, ReportFile]);
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(SI);
if not CreateProcess(nil, PChar(Cmd), nil, nil, False,
CREATE_NO_WINDOW, nil, nil, SI, PI) then
RaiseLastOSError;
try
WaitForSingleObject(PI.hProcess, 120000); // bound the wait per file
GetExitCodeProcess(PI.hProcess, Result);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
end;
Das Timeout ist keine Dekoration. Eine beschädigte Datei kann jeden Parser in pathologisches Gebiet treiben, und ein unbegrenztes Warten in einem Queue-Worker reißt die ganze Warteschlange mit. Begrenzen Sie die Wartezeit, behandeln Sie einen Timeout als Fehler mit eigenem Code und stellen Sie die Eingabe für eine manuelle Prüfung unter Quarantäne. Parsen Sie das XML nach Regelkennungen, statt menschenlesbare Meldungen auszulesen; Regel-IDs bleiben über Validator-Releases stabil, Meldungstexte nicht, und stabile Codes sind das, wonach Supportmitarbeiter in alten Tickets suchen können.
Batch-Verhalten verdient dieselbe Sorgfalt wie Einzeldokument-Korrektheit. Starten Sie den Validator als einen Prozess pro Datei statt als einen Prozess pro Stapel, damit eine pathologische Eingabe nur das Timeout dieser Datei kostet und nicht den gesamten Stapel; begrenzen Sie parallele Validator-Prozesse auf die Kernanzahl, weil XML-Berichtserzeugung CPU-gebunden ist; und setzen Sie beim Eingang eine Dateigrößengrenze, weil ein 2 GB großer Scan-Koloss die Warteschlange dominiert, egal wie gutmütig der Parser ist. Nichts davon ist Preflight-Logik, aber es ist der Unterschied zwischen einem Gate, das Monatsendvolumen übersteht, und einem Gate, das beim ersten Blockieren der Pipeline um 2 Uhr morgens deaktiviert wird.
PDF/X ist die Lücke in dieser Geschichte: veraPDF deckt es nicht ab, und die praktische Prüfung bleibt Acrobat Preflight mit dem passenden ISO-15930-Profil. Acrobat ist interaktiv, daher verwenden Sie ihn für Stichproben, für das erste Exemplar eines neuen Templates und für eine kleine Zufallsauswahl pro Stapel, während das automatisierte Gate abdeckt, was automatisierbar ist. Eine manuelle Stichprobe, die tatsächlich stattfindet, ist besser als eine theoretische Vollautomatisierung, die niemand fertig gebaut hat.
Was im Bericht stehen muss, damit er aufbewahrenswert ist
Ein Preflight-Gate erzeugt zweimal Wert: einmal, wenn es eine schlechte Datei blockiert, und erneut Monate später, wenn jemand fragt, warum eine Datei akzeptiert wurde. Der zweite Nutzen bestimmt das Berichtsformat. Halten Sie für jede geprüfte Datei fest: den Eingabe-Hash, die Compliance-Flags und Version des Generators aus der oben genannten Logzeile, Name und Version des Validators, das geprüfte Profil, ob das Ergebnis bestanden oder fehlgeschlagen ist, sowie die Liste fehlgeschlagener Regel-IDs mit Seitennummern, sofern der Validator sie liefert. Speichern Sie den Bericht neben dem Artefakt, das er beschreibt, nicht in einem separaten System, das vor dem Archiv außer Betrieb genommen wird.
Akzeptierte Abweichungen brauchen ebenfalls Dokumentation. Wenn ein Kunde darauf besteht, eine Datei auszuliefern, die dem Gate missfällt, halten Sie fest, wer sie freigegeben hat, warum und bis wann, und hängen Sie diese Ausnahme an den Bericht, statt die Regel global zu schwächen. Eine Ausnahme mit Verantwortlichem und Ablaufdatum ist ein verwalteter Sonderfall; eine auskommentierte Prüfung ist ein zukünftiger Vorfall.
Fehler verdienen noch einen weiteren Schritt: Kopieren Sie die fehlschlagende Datei in einen benannten Regressionsordner. Jeder Preflight-Vorfall, den wir debuggen halfen, lief am Ende auf eine reproduzierbare Eingabe hinaus, und Teams, die diese Eingaben aufbewahrten, behoben Regressionen in Stunden, statt sie in Produktion neu zu entdecken.
FAQ
Kann HotPDF ein beliebiges PDF eines Drittanbieters programmatisch validieren?
Nein. Der Preflight-Bericht im Produkt ist eine GUI-Demo-Funktion, keine aufrufbare API. Das unterstützte Automatisierungsmuster ist erzwingende Generierung über die Compliance-Eigenschaften plus ein externer Validator wie veraPDF für das formale Urteil.
Reicht veraPDF für Druckaufträge aus?
Es deckt PDF/A und PDF/UA ab. Für PDF/X-Druckmaster führen Sie Acrobat Preflight mit dem Profil aus, das Ihre Druckerei vorgibt, und bestätigen, dass der Output Intent zu der erwarteten Druckbedingung passt.
Was soll den Build fehlschlagen lassen: nur Fehler oder auch Warnungen?
Blockieren Sie bei Regelverstößen gegen das Profil, dessen Konformität Sie behaupten, und protokollieren Sie Warnungen mit Trendüberwachung. Jede Warnung zum Blocker zu machen trainiert Menschen darauf, das Gate zu umgehen, was schlechter ist als gar kein Gate.
Produktreferenz
Die in dieser Pipeline verwendeten Compliance-Eigenschaften und die Direct File API gehören zur HotPDF Component für Delphi und C++Builder; die Dokumentation beschreibt jeden hier gezeigten Aufruf vollständig.