THotPDF Preflight Report Methods

Składnia

type
  THPDFPreflightFormat = (pfText, pfJSON, pfHTML, pfCSV);

function CreatePreflightReport(
  const SourceFile: TFileName;
  const Password  : AnsiString = ''): AnsiString; overload;
function CreatePreflightReport(
  const SourceFile: TFileName;
  const Password  : AnsiString;
  const Format    : THPDFPreflightFormat): AnsiString; overload;
procedure SavePreflightReport(
  const SourceFile: TFileName;
  const ReportFile: TFileName;
  const Password  :AnsiString = ''); overload;
procedure SavePreflightReport(
  const SourceFile: TFileName;
  const ReportFile: TFileName;
  const Password  : AnsiString;
  const Format    : THPDFPreflightFormat); overload;
function ValidatePDFVT(
  const SourceFile: TFileName;
  out Report      : AnsiString): Boolean;
function ValidatePDFVT(
  const SourceFile: TFileName;
  const Password  : AnsiString;
  out Report      : AnsiString): Boolean;
procedure EmbedPreflightReportInPDF(
  const SourceFile: TFileName;
  const TargetFile: TFileName);
procedure EmbedPreflightReportInPDF(
  const SourceFile: TFileName;
  const TargetFile: TFileName;
  const Password  : AnsiString);
function LoadAndValidatePreflightReport(
  const EmbeddedFile  : TFileName;
  out OriginalReport: AnsiString;
  out CurrentReport : AnsiString): Boolean;
function LoadAndValidatePreflightReport(
  const EmbeddedFile  : TFileName;
  const Password      : AnsiString;
  out OriginalReport: AnsiString;
  out CurrentReport : AnsiString): Boolean;
function ComparePreflightReports(
  const ReportA: AnsiString;
  const ReportB: AnsiString): AnsiString;
function RepairPDFFromPreflightReport(
  const SourceFile: TFileName;
  const TargetFile: TFileName;
  out RepairsApplied: AnsiString): Boolean;
function RepairPDFFromPreflightReport(
  const SourceFile: TFileName;
  const TargetFile: TFileName;
  const Password  : AnsiString;
  out RepairsApplied: AnsiString): Boolean;
function AggregatePreflightReports(
  const Reports: array of AnsiString): AnsiString;
type
  THPDFPreflightProfile = record
    DisableChecks  : AnsiString;
    DisableWarnings: AnsiString;
    DisableHints   : Boolean;
  end;
function LoadPreflightProfile(
  const ProfileFile: TFileName): THPDFPreflightProfile;
function ApplyPreflightProfile(
  const Report : AnsiString;
  const Profile: THPDFPreflightProfile): AnsiString;
function ValidatePreflightProfile(
  const Profile: THPDFPreflightProfile;
  out UnknownNames: AnsiString): Boolean;
function GetBuiltInPreflightProfile(
  const Name: AnsiString): THPDFPreflightProfile;
procedure SavePreflightProfile(
  const Profile    : THPDFPreflightProfile;
  const ProfileFile: TFileName);
function CreatePreflightReportWithProfile(
  const SourceFile : TFileName;
  const Password   : AnsiString;
  const ProfileFile: TFileName;
  const Format     : THPDFPreflightFormat): AnsiString;
function MergePreflightProfiles(
  const A, B: THPDFPreflightProfile): THPDFPreflightProfile;
function DiffPreflightProfiles(
  const A, B  : THPDFPreflightProfile;
  out OnlyInA: AnsiString;
  out OnlyInB: AnsiString): Boolean;
procedure EmbedPreflightReportAsXMP(
  const SourceFile: TFileName;
  const TargetFile: TFileName);
procedure EmbedPreflightReportAsXMP(
  const SourceFile: TFileName;
  const TargetFile: TFileName;
  const Password  : AnsiString);
function ConvertPreflightReportToVeraPDFStyle(
  const Report: AnsiString): AnsiString;

Opis

CreatePreflightReport odczytuje wejściowy PDF i zwraca raport tekstowy z lekkimi kontrolami struktury. Przeciążenia z hasłem używają istniejącej ścieżki ładowania obsługującej hasła dla wspieranych szyfrowanych PDF. SavePreflightReport zapisuje ten sam raport do docelowego pliku tekstowego.

ValidatePDFVT uruchamia ukierunkowaną walidację PDF/VT i zwraca True tylko wtedy, gdy wymagane znaczniki i struktury są obecne. Zwrócony raport tekstowy sprawdza deklarację XMP pdfvtid:GTS_PDFVTVersion, przestrzeń nazw metadanych PDF/VT, zgodność daty modyfikacji PDF/VT z xmp:ModifyDate, bazowy znacznik PDF/X, brak szyfrowania, intencję wyjściową PDF/X, katalogowe DPartRoot, DPartRootNode, NodeNameList, obecność części dokumentu, ładowalną liczbę stron oraz pokrycie DPart na poziomie strony. Właściwości dat PDF/VT i XMP mogą być zapisane jako tekst elementu albo jako atrybuty RDF na elemencie rdf:Description.

Raport sprawdza nagłówek PDF, znacznik EOF, czy końcowy %%EOF leży blisko końca pliku, ostatni offset startxref, czy ten offset wskazuje tabelę xref albo strumień xref, liczbę znaczników %%EOF i startxref, równowagę znaczników rewizji i końcową kolejność znaczników, znacznik trailera albo strumienia XRef, ładowalną liczbę stron, stan szyfrowania, katalog, drzewo stron, znacznik obiektu strony, MediaBox, referencję słownika informacji, referencję root, liczbę obiektów pośrednich, liczbę definicji obiektów pośrednich, najwyższy numer obiektu, liczbę zduplikowanych numerów obiektów, unikalność numerów obiektów, liczbę obiektów katalogu, liczbę obiektów drzewa stron, liczbę obiektów stron, zadeklarowaną liczbę stron w drzewie stron, spójność liczby stron drzewa stron i ładowalnych stron, spójność obiektów stron i ładowalnych stron, równowagę stream i endstream, pokrycie wpisów /Length strumieni, liczbę tabel xref, liczbę podsekcji xref, liczby wpisów tabel xref, liczby wolnych i używanych wpisów xref, liczbę uszkodzonych wierszy xref, poprawność wierszy xref, pokrycie xref względem numerów obiektów, liczbę strumieni xref, liczbę strumieni obiektów, liczbę trailerów, trailer /Size, czy trailer /Size obejmuje najwyższy numer obiektu, pośrednie referencje trailera /Root i /Info, czy wskazane obiekty są zdefiniowane, czy trailer /Root wskazuje obiekt katalogu, liczbę wpisów tablicy trailer /ID i strukturę par, obecność trailer /Root, /Info, /ID i /Encrypt, szacowaną liczbę aktualizacji przyrostowych, status linearyzacji, załadowane pola stron, liczbę pól formularza, liczbę słowników zasobów, liczbę zasobów fontów, liczbę osadzonych programów fontów (/FontFile, /FontFile2, /FontFile3), liczbę image XObject, liczbę form XObject, liczbę zasobów ColorSpace, liczbę adnotacji oraz podliczby adnotacji widget/link, liczniki użycia łańcuchów filtrów dla FlateDecode, DCTDecode, CCITTFaxDecode, JBIG2Decode, LZWDecode, ASCIIHexDecode, ASCII85Decode, RunLengthDecode i JPXDecode, pokrycie osadzania fontów, spójność liczby adnotacji, wskazówki zgodności PDF/A / PDF/X / PDF/UA / Tagged PDF / transparency, wybrane flagi funkcji, ostrzeżenia JavaScript albo action (obejmujące pełny zestaw PDF 1.7 sec 12.6.4 action: GoTo*, Thread, URI, Sound, Movie, Hide, Named, SubmitForm, ResetForm, ImportData, SetOCGState, Rendition, Trans i GoTo3DView, plus starsze kontrole JavaScript / Launch / OpenAction / AdditionalActions / EmbeddedFile / RichMedia oraz ostrzeżenia wzajemnego wykluczenia PDF/A), sumy ostrzeżeń oraz ogólne podsumowanie pass/fail. Te pomocniki są przeznaczone jako szybkie kontrole in-process przed przekazaniem plików do zewnętrznych walidatorów standardów; nie zastępują pełnego silnika walidacji preflight PDF/A, PDF/X, PDF/UA ani ISO 32000.

Overload Format przyjmuje pfText (domyślna ścieżka czysto tekstowa, stabilna bajtowo ze starymi overloadami), pfJSON (dokument JSON przyjazny CI), pfHTML (gotowy na dashboard, samowystarczalny raport HTML z inline CSS i wierszami barwionymi wg wagi) albo pfCSV (wiersze przyjazne arkuszom dla metadanych, checków, hintów, ostrzeżeń i wartości podsumowania). Wyjście JSON grupuje wpisy w polach najwyższego poziomu input, size, pdfVersion i xrefStyle plus tablice checks, info, hints i warnings oraz obiekt summary niosący wartości failed, warnings i result. Każdy check, hint i ostrzeżenie niesie też stabilny, mający przestrzeń nazw ruleId oraz ustrukturyzowany obiekt location Lokalizacja zawsze zawiera logiczny scope i rozdzielaną ukośnikami path, może zawierać powiązany key PDF i dodaje objectNumber, pageIndex albo byteOffset, gdy raport potrafi wskazać dokładną współrzędną. Wyjście CSV używa stabilnego nagłówka category,name,status,value,spec, z tekstami referencji ISO w spec, gdy diagnostyka ma zmapowaną klauzulę standardu. Wbudowany enkoder JSON escapuje ", \ i bajty sterujące; sekwencje bajtów UTF-8 przechodzą bez zmian.

Każdy wpis checks, hints i warnings niesie opcjonalne pole spec nazywające klauzulę ISO, na którą celuje diagnostyka (np ISO 32000-1 sec 7.5.5 dla checków trailera, ISO 19005-1 sec 6.6.2 dla ostrzeżenia o wzajemnej wykluczalności PDF/A z JavaScriptem). Mapowanie obejmuje każdy check, hint i ostrzeżenie emitowane przez raport do v2.122.0. Formalny JSON Schema (draft 2020-12) opisujący strukturę wyjścia pfJSON jest opublikowany w Docs/preflight-schema.json, więc konsumenci downstream mogą walidować wyjście przed parsowaniem ID reguł mają stabilną formę hotpdf.preflight.<category>.<rule-name>, więc polityki CI mogą matchować regułę bez zależności od przetłumaczonej prozy albo pozycji w tablicy

EmbedPreflightReportInPDF zapisuje kopię źródłowego PDF do TargetFile z raportem preflight w starszym formacie tekstowym dołączonym po ostatnim %%EOF jako linie komentarzy w stylu PDF (każda linia poprzedzona % ). Czytniki PDF ignorują dołączone bajty, ponieważ znajdują się poza grafem obiektów, ale przepływy archiwizacji, edytory tekstu i narzędzia w stylu grep mogą nadal odnaleźć osadzony raport do późniejszego audytu. Oryginalny graf obiektów, tabela cross-reference i trailer nie są modyfikowane.

LoadAndValidatePreflightReport wyodrębnia raport, który wcześniej dołączyło EmbedPreflightReportInPDF, ponownie uruchamia bieżący algorytm preflight na bajtach źródła poprzedzających osadzony blok komentarza i porównuje wartości InputFingerprint. Funkcja zwraca True, gdy oba odciski się zgadzają, co oznacza, że osadzony raport nadal opisuje plik w takiej postaci, w jakiej istnieje na dysku Gdy walidacja się nie powiedzie, wywołujący może sprawdzić OriginalReport i CurrentReport, aby zobaczyć diff zmian

ComparePreflightReports generuje treść w stylu unified diff dla dwóch raportów. Wspólne wiersze pojawiają się z prefiksem dwóch spacji, wiersze unikalne dla ReportA mają prefiks - , a wiersze unikalne dla ReportB — prefiks + . Algorytm jest dostrojony do poprawnie sformowanego wyjścia klucz/wartość produkowanego przez CreatePreflightReport, gdzie kolejność wierszy jest deterministyczna; nie jest to ogólna implementacja LCS, ale daje zwarte, czytelne diffy w typowym przypadku raportów w większości niezmienionych

RepairPDFFromPreflightReport stosuje zachowawczy podzbiór napraw na poziomie bajtów uszkodzonego pliku PDF: odcina końcowe bajty następujące po ostatnim markerze %%EOF i dopisuje brakujący %%EOF, jeśli nie ma go nigdzie w pliku. Funkcja zwraca True, gdy zastosowano co najmniej jedną naprawę; RepairsApplied wymienia naprawy w jednym wierszu na zmianę. Naprawy na poziomie grafu obiektów (odbudowa tablic xref, łatanie długości strumieni, poprawianie słowników trailera) są celowo poza zakresem, bo takie poprawki mogą pogorszyć odzyskiwalność pliku częściowo odzyskiwalnego; przy głębszych uszkodzeniach użyj dedykowanego narzędzia do odzyskiwania PDF

AggregatePreflightReports przyjmuje tablicę raportów per plik i tworzy jedno podsumowanie batch. Każdy wpis tablicy jest parsowany pod kątem pól Input, Size i Summary; agregat emituje jedną linię na plik oraz sumy liczby raportów passed, failed i warning, łącznych przeskanowanych bajtów oraz ogólnych liczników wyników. Przydatne dla potoków CI i pętli shell, które przetwarzają katalog PDF i chcą jednego zwięzłego podsumowania na końcu.

LoadPreflightProfile i ApplyPreflightProfile pozwalają dostosować wyjście raportu bez ponownego uruchamiania analizy. Plik profilu używa formatu w stylu INI z trzema opcjonalnymi sekcjami: [disable-checks] wymienia nazwy sprawdzeń do pominięcia; [disable-warnings] wymienia nazwy ostrzeżeń do pominięcia; a [options] akceptuje hints=false, aby pominąć każdy wiersz Hint. Po filtrowaniu wiersz Summary jest przeliczany, tak aby pominięte wpisy nie wpływały już na sumy Failed i Warnings; reszta raportu przechodzi bez zmian

ValidatePreflightProfile przechodzi przez listy DisableChecks i DisableWarnings załadowanego profilu i zgłasza każdą nazwę nierozpoznawaną przez bieżącą implementację preflight. Pomaga wykryć pliki profili napisane dla nowszej lub starszej wersji HotPDF, które w przeciwnym razie po cichu nie wyłączyłyby niczego, ponieważ nazwy nie pasują do żadnej emitowanej kontroli ani ostrzeżenia.

GetBuiltInPreflightProfile zwraca gotowe do użycia rekordy profili dla typowych przepływów. Rozpoznawane nazwy (bez rozróżniania wielkości liter): default / '' zwraca pusty profil; compact wyłącza każdy wiersz Hint dla krótszych raportów; silent-actions wyłącza każde ostrzeżenie o akcji z PDF 1.7 sec 12.6.4 oraz EmbeddedFile i RichMedia, z myślą o przepływach, które celowo osadzają multimedia lub akcje interaktywne i nie chcą, by raport preflight je oznaczał. Nieznane nazwy również zwracają pusty profil

SavePreflightProfile zapisuje rekord THPDFPreflightProfile z powrotem do pliku INI w tym samym formacie, który odczytuje LoadPreflightProfile Obie funkcje są dokładnie odwrotne dla poprawnie sformowanych profili, więc wywołujący mogą zbudować przepływ „wczytaj preset, popraw, zapisz”: P := GetBuiltInPreflightProfile('compact'), edycja P.DisableChecks, a potem SavePreflightProfile(P, 'tuned.ini') do późniejszego ponownego użycia

CreatePreflightReportWithProfile to wygodny wrapper jednego kroku, który składa istniejące CreatePreflightReport, LoadPreflightProfile, ApplyPreflightProfile i konwertery formatów, dzięki czemu wywołujący mający już źródłowy PDF, opcjonalne hasło, plik profilu i format docelowy może wykonać jedno wywołanie zamiast łączyć cztery. Przekazanie pustego ProfileFile pomija krok profilu.

MergePreflightProfiles zwraca zdeduplikowaną sumę dwóch profili: DisableChecks i DisableWarnings zbierają nazwy z obu wejść, a DisableHints jest logicznym OR. Przydatne do nakładania presetu na poprawki specyficzne dla projektu.

DiffPreflightProfiles raportuje strukturalną różnicę między dwoma profilami. Zwraca True, gdy są równoważne; w przeciwnym razie False, a OnlyInA i OnlyInB są wypełnione wierszami rozdzielonymi znakiem nowej linii w postaci check:<name>, warn:<name> lub option:hints=false, opisującymi, które wpisy występują tylko po jednej stronie

EmbedPreflightReportAsXMP to wariant EmbedPreflightReportInPDF przyjazny archiwizacji: zapisuje kopię źródłowego PDF z raportem preflight dołączonym jako blok komentarza w stylu PDF, którego payload to XMP / RDF (xmlns:hotpdf="http://www.loslab.com/hotpdf/preflight/") Każdy wiersz raportu staje się elementem hotpdf:<name>, a poziom ważności jest przenoszony jako atrybut w wierszach sprawdzeń Narzędzia obsługujące XMP, które skanują plik w poszukiwaniu markerów xpacket, mogą wyświetlić osadzony raport; czytniki PDF nadal ignorują dołączone bajty, bo leżą poza grafem obiektów. To celowo nie jest integracja XMP zgodna ze specyfikacją: payload XMP nie jest referencjonowany z wpisu /Metadata katalogu, więc czytniki XMP, które podążają tylko za referencją z katalogu, go nie zobaczą

ConvertPreflightReportToVeraPDFStyle formuje raport preflight HotPDF w dokument JSON podążający za ogólnym zarysem wyjścia walidacji veraPDF, z poliem najwyższego poziomu profile, tablicą jobs zawierającą itemDetails / taskResult / validationResult i tablicą ruleViolations pod validationResult.details. Stylizowane na HotPDF, a nie kompatybilne po drucie z veraPDF; celem jest pozwolić narzędziom downstream, które już konsumują JSON veraPDF, zaadaptować się do wyjścia HotPDF z minimalnym remapowaniem nazw pól, zamiast uczyć się kompletnie innego układu danych Każde violation niesie ten sam stabilny ruleId i ustrukturyzowaną location, których używa natywny raport JSON

Przykład

var
  PDF: THotPDF;
begin
  PDF := THotPDF.Create(nil);
  try
    PDF.SavePreflightReport('Input.pdf', 'PreflightReport.txt');
    PDF.SavePreflightReport('Encrypted.pdf', 'EncryptedReport.txt', 'user-password');
    PDF.SavePreflightReport('Input.pdf', 'PreflightReport.json', '', pfJSON);
    PDF.SavePreflightReport('Input.pdf', 'PreflightReport.html', '', pfHTML);
    PDF.SavePreflightReport('Input.pdf', 'PreflightReport.csv', '', pfCSV);
    PDF.EmbedPreflightReportInPDF('Input.pdf', 'Input-with-report.pdf');
    if not PDF.LoadAndValidatePreflightReport(
      'Input-with-report.pdf', OriginalReport, CurrentReport)
    then
      WriteLn('Embedded preflight report no longer matches the source.');
  finally
    PDF.Free;
  end;
end;

Zobacz też