เมธอดรายงาน THotPDF Preflight

ไวยากรณ์

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

function CreatePreflightReport(const SourceFile: TFileName): AnsiString;
function CreatePreflightReport(
  const SourceFile: TFileName;
  const Password  : AnsiString): AnsiString;
function CreatePreflightReport(
  const SourceFile: TFileName;
  const Password  : AnsiString;
  const Format    : THPDFPreflightFormat): AnsiString;
procedure SavePreflightReport(
  const SourceFile: TFileName;
  const ReportFile: TFileName);
procedure SavePreflightReport(
  const SourceFile: TFileName;
  const ReportFile: TFileName;
  const Password  : AnsiString);
procedure SavePreflightReport(
  const SourceFile: TFileName;
  const ReportFile: TFileName;
  const Password  : AnsiString;
  const Format    : THPDFPreflightFormat);
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;

คำอธิบาย

CreatePreflightReport อ่าน input PDF และคืน text report ที่มี lightweight structural checks password overloads ใช้ password-aware load path ที่มีอยู่สำหรับ encrypted PDFs ที่รองรับ SavePreflightReport เขียน report เดียวกันลง target text file

ValidatePDFVT รัน validation pass ที่เจาะจง PDF/VT และคืน True เฉพาะเมื่อ markers และ structures ที่ต้องมีอยู่ครบ text report ที่คืนมาจะตรวจ pdfvtid:GTS_PDFVTVersion XMP claim, PDF/VT metadata namespace, ความตรงกันของ PDF/VT modification date กับ xmp:ModifyDate, PDF/X base marker, การไม่มี encryption, PDF/X output intent, catalog DPartRoot, DPartRootNode, NodeNameList, document part presence, loadable page count, และ page-level DPart coverage PDF/VT และ XMP date properties สามารถเขียนเป็น element text หรือ RDF attributes บน rdf:Description element ได้

report ตรวจ PDF header, EOF marker, ว่า %%EOF marker สุดท้ายอยู่ใกล้ท้าย file หรือไม่, last startxref offset, offset นั้นชี้ไปที่ xref table หรือ xref stream หรือไม่, จำนวน %%EOF และ startxref markers, revision marker balance และ final marker ordering, trailer หรือ XRef stream marker, loadable page count, encryption state, catalog, page tree, page object marker, MediaBox, information dictionary reference, root reference, indirect object count, indirect object definition count, highest object number, duplicate object number count, object number uniqueness, catalog object count, page tree object count, page object count, page tree declared page count, page tree count/loadable page consistency, page object/loadable page consistency, balance ของ stream และ endstream, stream /Length entry coverage, xref table count, xref subsection count, xref table entry counts, xref free / in-use entry counts, malformed xref row count, xref row validity, xref coverage against object numbers, xref stream count, object stream count, trailer count, trailer /Size, ว่า trailer /Size cover highest object number หรือไม่, trailer /Root และ /Info indirect references, ว่า referenced objects เหล่านั้น defined หรือไม่, ว่า trailer /Root target catalog object หรือไม่, trailer /ID array entry count และ pair structure, presence ของ trailer /Root, /Info, /ID, /Encrypt, estimated incremental update count, linearization status, loaded page boxes, form field count, resource dictionary count, font resource count, embedded font program count (/FontFile, /FontFile2, /FontFile3), image XObject count, form XObject count, ColorSpace resource count, annotation count และ widget/link annotation subcounts, filter chain usage counts สำหรับ FlateDecode, DCTDecode, CCITTFaxDecode, JBIG2Decode, LZWDecode, ASCIIHexDecode, ASCII85Decode, RunLengthDecode, JPXDecode, font embedding coverage, annotation count consistency, PDF/A / PDF/X / PDF/UA / Tagged PDF / transparency compliance hints, selected feature flags, JavaScript หรือ action warnings รวมทั้ง PDF 1.7 sec 12.6.4 action set ทั้งหมดและ legacy JavaScript / Launch / OpenAction / AdditionalActions / EmbeddedFile / RichMedia checks กับ PDF/A mutual-exclusion warnings, warning totals และ overall pass/fail summary helpers เหล่านี้เป็น fast in-process checks ก่อนส่ง files ไป external standards validators ไม่ใช่ตัวแทนของ full PDF/A, PDF/X, PDF/UA หรือ ISO 32000 preflight validation engine

Format overload รับ pfText ซึ่งเป็น default plain-text path ที่ byte-stable กับ legacy overloads, pfJSON สำหรับ CI-friendly JSON document, pfHTML สำหรับ self-contained HTML report พร้อม inline CSS และ severity-colored rows, หรือ pfCSV สำหรับ spreadsheet-friendly rows ของ metadata, checks, hints, warnings และ summary values JSON output จัดกลุ่ม entries เป็น top-level fields input, size, pdfVersion, xrefStyle รวมถึง arrays checks, info, hints, warnings และ summary object ที่มี failed, warnings, result values CSV output ใช้ stable header category,name,status,value,spec โดยมี ISO reference text ใน spec เมื่อ diagnostic มี mapped standard clause built-in JSON encoder escape ", \ และ control bytes ส่วน UTF-8 byte sequences ผ่าน unchanged

entry แต่ละรายการใน checks, hints, และ warnings มี optional spec field เพื่อระบุ ISO clause ที่ diagnostic target เช่น ISO 32000-1 sec 7.5.5 สำหรับ trailer-related checks และ ISO 19005-1 sec 6.6.2 สำหรับ PDF/A with JavaScript mutual-exclusion warning mapping นี้ cover check, hint, warning ทุกตัวที่ report emit จนถึง v2.122.0 formal JSON Schema (draft 2020-12) ที่อธิบาย pfJSON output structure เผยแพร่ที่ Docs/preflight-schema.json เพื่อให้ downstream consumers validate output ก่อน parse ได้

EmbedPreflightReportInPDF เขียน copy ของ source PDF ไปที่ TargetFile โดย append legacy text-format preflight report หลัง %%EOF สุดท้ายเป็น PDF-style comment lines แต่ละ line มี prefix PDF readers จะ ignore bytes ที่ append เพราะอยู่นอก object graph แต่ archive workflows, text editors และ grep-style tools ยังมองเห็น embedded report สำหรับ audit ภายหลังได้ original object graph, cross-reference table และ trailer ไม่ถูกแก้

LoadAndValidatePreflightReport extract report ที่ EmbedPreflightReportInPDF เคย append, rerun preflight algorithm ปัจจุบันกับ source bytes ก่อน embedded comment block และ compare ค่า InputFingerprint function คืน True เมื่อ fingerprints ทั้งสองตรงกัน ซึ่งบอกว่า embedded report ยังอธิบาย file ตามที่อยู่บน disk ได้ เมื่อ validation fail callers สามารถ inspect OriginalReport และ CurrentReport เพื่อ diff สิ่งที่เปลี่ยนได้

ComparePreflightReports emit body แบบ unified-diff-like สำหรับ reports สองชุด shared lines ใช้ two-space prefix, lines ที่มีเฉพาะใน ReportA ใช้ prefix -, และ lines ที่มีเฉพาะใน ReportB ใช้ prefix + algorithm นี้ปรับสำหรับ key/value output ที่ well-formed จาก CreatePreflightReport ซึ่ง line order deterministic ไม่ใช่ general-purpose LCS implementation แต่สร้าง diff ที่ compact และอ่านง่ายสำหรับกรณีทั่วไปที่ report ส่วนใหญ่ไม่เปลี่ยน

RepairPDFFromPreflightReport ใช้ byte-level repairs แบบ conservative subset กับ damaged PDF โดยลบ trailing bytes หลัง %%EOF marker สุดท้าย และ append %%EOF ที่หายไปเมื่อไม่มีอยู่ใน file function คืน True เมื่อมี repair อย่างน้อยหนึ่งรายการ RepairsApplied แสดง repairs หนึ่ง line ต่อ change object-graph repairs เช่น rebuild xref tables, patch stream lengths, fix trailer dictionaries อยู่นอก scope โดยตั้งใจ เพราะอาจทำให้ partially-recoverable file recover ได้ยากขึ้น ควรใช้ dedicated PDF recovery tool สำหรับ damage ที่ลึกกว่า

AggregatePreflightReports รับ array ของ per-file reports และสร้าง batch summary เดียว แต่ละ entry ใน array ถูก parse จาก fields Input, Size, Summary aggregate emit หนึ่ง line ต่อ file พร้อม totals สำหรับจำนวน passed, failed และ warning reports, total bytes scanned และ overall result counts เหมาะกับ CI pipelines และ shell loops ที่ process directory ของ PDFs และต้องการ summary สั้นท้ายงาน

LoadPreflightProfile และ ApplyPreflightProfile ให้ callers ปรับ report output ได้โดยไม่ rerun analysis profile file ใช้ INI-style format มี optional sections สามส่วน: [disable-checks] ระบุ check names ที่ suppress, [disable-warnings] ระบุ warning names ที่ suppress, และ [options] รับ hints=false เพื่อ suppress ทุก Hint line หลัง filtering จะ recompute Summary line เพื่อไม่ให้ suppressed entries นับใน Failed และ Warnings totals ส่วนที่เหลือของ report ผ่าน unchanged

ValidatePreflightProfile เดินผ่าน lists DisableChecks และ DisableWarnings ของ loaded profile แล้วรายงาน name ที่ preflight implementation ปัจจุบันไม่รู้จัก เหมาะสำหรับตรวจ profile files ที่เขียนกับ HotPDF version ใหม่กว่าหรือเก่ากว่า ซึ่งอาจไม่ disable อะไรเลยเพราะชื่อไม่ตรงกับ check หรือ warning ที่ emit

GetBuiltInPreflightProfile คืน ready-to-use profile records สำหรับ common workflows names ที่รู้จักแบบ case-insensitive: default / '' คืน empty profile, compact disable ทุก Hint line เพื่อให้ report สั้นลง, silent-actions disable ทุก PDF 1.7 sec 12.6.4 action warning รวมถึง EmbeddedFile และ RichMedia สำหรับ workflows ที่ตั้งใจ embed multimedia หรือ interactive actions และไม่ต้องการให้ preflight report flag ค่า unknown names ก็คืน empty profile

SavePreflightProfile เขียน THPDFPreflightProfile record กลับเป็น INI file ใน format เดียวกับที่ LoadPreflightProfile consume สอง functions นี้เป็น exact inverses สำหรับ profiles ที่ well-formed ทำให้ callers สร้าง workflow แบบ load preset, tweak, save ได้ เช่น P := GetBuiltInPreflightProfile('compact'), แก้ P.DisableChecks, แล้ว SavePreflightProfile(P, 'tuned.ini') เพื่อใช้ภายหลัง

CreatePreflightReportWithProfile เป็น one-stop convenience wrapper ที่ประกอบ CreatePreflightReport, LoadPreflightProfile, ApplyPreflightProfile และ format converters เพื่อให้ caller ที่มี source PDF, optional password, profile file และ target format อยู่แล้วเรียกครั้งเดียวแทน chain สี่ครั้งได้ การส่ง empty ProfileFile จะ skip profile step

MergePreflightProfiles คืน deduplicated union ของ profiles สองชุด โดย DisableChecks และ DisableWarnings รวม names จาก inputs ทั้งคู่ ส่วน DisableHints เป็น logical OR เหมาะสำหรับ layer preset ทับ project-specific tweaks

DiffPreflightProfiles รายงาน structural difference ระหว่าง profiles สองชุด คืน True เมื่อ equivalent ไม่เช่นนั้นคืน False พร้อมเติม OnlyInA และ OnlyInB ด้วย newline-separated lines รูปแบบ check:<name>, warn:<name> หรือ option:hints=false เพื่อบอกว่า entries ใดอยู่เฉพาะฝั่งหนึ่ง

EmbedPreflightReportAsXMP เป็น variant ที่เหมาะกับ archival ของ EmbedPreflightReportInPDF โดยเขียน copy ของ source PDF พร้อม append preflight report เป็น PDF-style comment block ที่ payload เป็น XMP / RDF (xmlns:hotpdf="http://www.loslab.com/hotpdf/preflight/") แต่ละ report line กลายเป็น hotpdf:<name> element พร้อม severity เป็น attribute บน check rows tools ที่รู้จัก XMP และ scan หา xpacket markers สามารถแสดง embedded report ได้ PDF readers ยังคง ignore bytes ที่ append เพราะอยู่นอก object graph นี่ไม่ใช่ spec-compliant XMP integration โดยตั้งใจ เพราะ XMP payload ไม่ได้ referenced จาก catalog /Metadata entry ดังนั้น XMP readers ที่ follow เฉพาะ catalog reference จะไม่เห็น

ConvertPreflightReportToVeraPDFStyle แปลง HotPDF preflight report เป็น JSON document ที่ตามโครงกว้างของ validation output ของ veraPDF มี top-level profile field, jobs array ที่มี itemDetails / taskResult / validationResult, และ ruleViolations array ใต้ validationResult.details เป็น HotPDF-styled ไม่ใช่ wire-compatible กับ veraPDF เป้าหมายคือให้ downstream tooling ที่ consume veraPDF JSON อยู่แล้วปรับเข้ากับ HotPDF output ด้วย field-name remapping น้อยที่สุด แทนการเรียน data layout ใหม่ทั้งหมด

ตัวอย่าง

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;

ดูเพิ่มเติม

  • ตำราอาหารการตรวจสอบก่อนการพิมพ์
  • โครงสร้างแผนผัง Preflight API
  • LoadFromFile
  • GetLoadedPageBox
  • เมธอดฟิลด์ฟอร์มที่โหลด