Technical Article

Rješavanje hibridnih referentnih PDF-ova iz Office aplikacija u Delphiju

Prilikom razvoja poslovnih rješenja za dokumente, neizbježno ćete naići na PDF-ove koje generira mnoštvo različitih alata, od vrhunskog Adobe softvera do open-source biblioteka prepunih grešaka ili virtualnih upravljačkih programa za pisače. Jedan od najozloglašenijih strukturnih problema s kojim ćete se suočiti je "hibridni referentni" PDF.

U ovom ćemo članku objasniti što su hibridne reference, zašto ih određene uredske aplikacije generiraju i kako programski parsirati i popraviti te strukture pomoću Delphija i robusnih PDF biblioteka.

Evolucija PDF tablice unakrsnih referenci

Za brzo lociranje objekata (fontova, slika, stranica) bez parsiranja cijele datoteke, PDF koristi tablicu unakrsnih referenci (XRef). U ranijim PDF specifikacijama (PDF 1.4 i starijima), to je doslovno bila ASCII tekstualna tablica na kraju datoteke.

Počevši od PDF-a 1.5, Adobe je uveo tokove unakrsnih referenci (XRefStm), koji su komprimirali podatke unakrsnih referenci u binarni tok, značajno smanjujući veličinu datoteka. Međutim, radi kompatibilnosti unatrag sa starijim PDF čitačima, neki generatori počeli su proizvoditi hibridne referentne PDF-ove. Ove datoteke sadrže i ASCII XRef tablicu starog stila i XRef tok novog stila.

Problem s hibridnim referencama

Hibridne datoteke su teoretski važeće, ali mnogi PDF generatori (posebno naslijeđeni dodaci "Spremi kao PDF" u starijim Office paketima) pišu ih pogrešno. Uobičajena greška je upisivanje pogrešnog pomaka u bajtovima za pokazivač `startxref` ili stvaranje nepovezanih tokova objekata gdje XRef tablica pokazuje na pogrešan generacijski broj.

Ako vaša Delphi aplikacija pokuša pročitati loše oblikovan hibridni PDF pomoću strogog parsera, parser će propasti s iznimkom "Corrupt XRef table" ili "Invalid Object Number".

Rukovanje hibridnim zamjenama pomoću PDFiuma

PDFium motor (izvorno razvijen od strane Foxita, a zatim ga je Google učinio otvorenim kodom) vrlo je tolerantan prema loše oblikovanim PDF-ovima. Kada otkrije oštećenu XRef tablicu, automatski skenira datoteku unatrag od EOF-a kako bi pronašao alternativni XRefStm.

U Delphiju, pri radu s PDFiumom, ne morate ručno parsirati rječnike trailera. Međutim, trebali biste provjeriti postoje li strukturna upozorenja kako biste mogli obavijestiti korisnika ili zabilježiti problem.

uses
  System.SysUtils, pdfium_lib;

procedure LoadAndCheckHybridPDF(const FileName: string);
var
  Doc: FPDF_DOCUMENT;
  LastError: ULONG;
begin
  FPDF_InitLibrary();
  try
    Doc := FPDF_LoadDocument(PAnsiChar(AnsiString(FileName)), nil);
    if Doc = nil then
    begin
      LastError := FPDF_GetLastError();
      case LastError of
        FPDF_ERR_FILE: Writeln('File not found or could not be opened.');
        FPDF_ERR_FORMAT: Writeln('File not in PDF format or corrupted.');
        FPDF_ERR_PASSWORD: Writeln('Password required or incorrect password.');
        FPDF_ERR_SECURITY: Writeln('Unsupported security scheme.');
        FPDF_ERR_XFDF: Writeln('Invalid XRef or Hybrid Reference structure.');
      else
        Writeln('Unknown error occurred loading PDF.');
      end;
      Exit;
    end;
    
    Writeln('PDF loaded successfully despite hybrid or structural anomalies.');
    
    // Proceed with processing...
    
    FPDF_CloseDocument(Doc);
  finally
    FPDF_DestroyLibrary();
  end;
end;

Popravljanje i ponovna izgradnja PDF-a

Ako vaš radni tijek zahtijeva prosljeđivanje PDF-a strožem sustavu u nizu (poput starijeg hardverskog RIP-a), morate "izravnati" hibridnu strukturu. Najpouzdaniji način za popravak oštećenog hibridnog PDF-a u Delphiju je učitavanje u tolerantan motor i izvođenje operacije Spremi kao. To prisiljava parser da ponovno izgradi čistu, unificiranu XRef tablicu iz stabla objekata u memoriji.

// Conceptual example using a high-level wrapper
procedure RebuildPdfStructure(const InputFile, OutputFile: string);
var
  Doc: TlxPDFDocument;
begin
  Doc := TlxPDFDocument.Create;
  try
    // Tolerant engine ignores the broken hybrid XRef and walks the objects
    Doc.LoadFromFile(InputFile);
    
    // Saving rewrites the file with a clean PDF 1.7 XRef stream
    Doc.SaveToFile(OutputFile);
    Writeln('PDF structure successfully rebuilt.');
  finally
    Doc.Free;
  end;
end;

Razumijevanje i predviđanje korupcije hibridnih referenci osigurava da vaši cjevovodi za obradu dokumenata ostanu otporni, čak i kada su suočeni s desetljećima starim naslijeđenim datotekama.

Napomena: Razlučivost hibridnih referenci i automatski strukturni popravci u potpunosti su podržani u PDFium Component.