기술 문서

HotPDF Component: Delphi에서 automated PDF preflight reports

HotPDF는 Delphi 및 C++Builder 애플리케이션을 위한 네이티브 VCL PDF 라이브러리입니다. 외부 PDF 런타임 배포 없이 PDF 생성, 편집, 양식, 주석, 암호화, 디지털 서명, Unicode 글꼴 처리, 표준 지향 출력, 프리플라이트 보고를 지원합니다.

이 글은 teams that need repeatable PDF intake, release gates, or customer-support diagnostics을 위한 글입니다. automated PDF preflight reports을 단순한 컴포넌트 호출이 아니라 운영 환경의 문서 엔지니어링으로 다룹니다.

실제 위험은 manual visual checks are inconsistent and do not create machine-readable evidence for operators, CI jobs, or support engineers입니다. 따라서 명확한 계약, 관찰 가능한 진단, 실제 고객 파일을 반영한 회귀 샘플이 필요합니다.

아키텍처 결정

Turn preflight into a policy service. profiles for intake, release, archive, print, and accessibility checks / severity thresholds, waiver rules, and customer-specific exceptions

  • profiles for intake, release, archive, print, and accessibility checks
  • severity thresholds, waiver rules, and customer-specific exceptions
  • report formats for humans, CI logs, dashboards, and support bundles
  • time limits, maximum file size, and quarantine behavior for damaged input

구현 흐름

Classify findings before deciding pass or fail. The order below keeps the workflow reviewable for Delphi and C++Builder teams.

  1. identify the business purpose before selecting the preflight profile
  2. run validation in an isolated step before editing or distributing the document
  3. normalize findings into stable codes, severities, locations, and remediation hints
  4. apply waiver policy after findings are classified, not before validation
  5. store the report beside the output or ticket that depends on it

검증 증거

Report fields that make findings actionable. Keep these fields with the output or support record.

  • profile version, input hash, validator version, elapsed time, and pass or fail result
  • finding code, severity, page, object reference, and operator-facing message
  • waiver identifier, reviewer, expiry, and affected issue codes
  • machine-readable summary for CI plus an HTML or text report for support

A report is only useful when it drives a decision

Preflight automation should map low-level PDF findings to product decisions. Operators need to know what failed, why it matters, whether retry is useful, and where the affected page or object can be inspected.

Decision table for automated PDF preflight reports

A decision table keeps product ownership visible when the same workflow is reused by a desktop tool, service job, and support utility.

DecisionEngineering reasonEvidence
profiles for intake, release, archive, print, and accessibility checksidentify the business purpose before selecting the preflight profileprofile version, input hash, validator version, elapsed time, and pass or fail result
severity thresholds, waiver rules, and customer-specific exceptionsrun validation in an isolated step before editing or distributing the documentfinding code, severity, page, object reference, and operator-facing message
report formats for humans, CI logs, dashboards, and support bundlesnormalize findings into stable codes, severities, locations, and remediation hintswaiver identifier, reviewer, expiry, and affected issue codes

automated PDF preflight reports에 대한 엔지니어링 검토 노트

이 검토 노트를 사용해 기능이 데모 단계를 넘어섰고 출시, 지원, 고객 에스컬레이션 상황에서 설명할 수 있는지 확인합니다

  • 결정: profiles for intake, release, archive, print, and accessibility checks. 구현상 핵심 지점: run validation in an isolated step before editing or distributing the document. 승인 증거: waiver identifier, reviewer, expiry, and affected issue codes. 회귀 트리거: support staff need stable issue codes rather than parser exception text
  • 결정: severity thresholds, waiver rules, and customer-specific exceptions. 구현상 핵심 지점: normalize findings into stable codes, severities, locations, and remediation hints. 승인 증거: machine-readable summary for CI plus an HTML or text report for support. 회귀 트리거: warnings can become release blockers when the target channel changes
  • 결정: report formats for humans, CI logs, dashboards, and support bundles. 구현상 핵심 지점: apply waiver policy after findings are classified, not before validation. 승인 증거: profile version, input hash, validator version, elapsed time, and pass or fail result. 회귀 트리거: batch preflight should limit memory and CPU per file to protect queues

경계 사례

  • warnings can become release blockers when the target channel changes
  • batch preflight should limit memory and CPU per file to protect queues
  • repairing input before preflight can hide the original customer issue
  • support staff need stable issue codes rather than parser exception text

Delphi / C++Builder 참고 사항

HotPDF Component should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. 중요한 용어는 preflight, validation profile, report automation, severity, waiver, CI gate.

Delphi 코드 예제

다음 Delphi 스케치는 이 주제에 맞는 실무형 서비스 경계를 보여 줍니다. 정책 검사, 로깅, 검증을 좁은 제품 호출 구간 밖에 두면 워크플로를 테스트하기 쉽습니다.

procedure RunPreflightBatch(const InputFile, ReportFile: string);
var
  Pdf: THotPDF;
  Profile: THPDFPreflightProfile;
  Report: string;
begin
  Pdf := THotPDF.Create(nil);
  try
    Profile := Pdf.GetBuiltInPreflightProfile('strict');
    Report := Pdf.CreatePreflightReportWithProfile(InputFile, Profile);
    TFile.WriteAllText(ReportFile, Report, TEncoding.UTF8);
    RaiseIfBlockingFindings(Report);
  finally
    Pdf.Free;
  end;
end;

운영 체크리스트

  • 워크플로는 빈 파일, 일반 고객 파일, 최악의 파일에서 실행합니다
  • 생성된 PDF는 대상 뷰어, 검증기, 프린터 또는 downstream 애플리케이션에서 엽니다
  • 제품 버전, 프로필 버전, 입력 해시, 출력 경로, 경과 시간, 경고 수를 기록합니다
  • 암호, 인증서, 임시 파일, 고객 데이터는 명확한 보존 규칙에 따라 관리합니다
  • 고객 파일이 새로운 경계 사례를 드러내면 회귀 문서를 추가합니다

제품 문서

HotPDF Component

추가 코드 예제

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;
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;