Technical Article

Office-sovellusten hybridiviite-PDF-tiedostojen käsittely Delphissä

Yritysasiakirjaratkaisuja kehitettäessä kohtaat väistämättä PDF-tiedostoja, jotka on luotu valtavalla valikoimalla työkaluja, huippuluokan Adobe-ohjelmistoista bugisiin avoimen lähdekoodin kirjastoihin tai virtuaalisiin tulostinohjaimiin. Yksi pahamaineisimmista rakenteellisista ongelmista, joita kohtaat, on "hybridiviitteinen" PDF.

Tässä artikkelissa selitämme, mitä hybridiviitteet ovat, miksi tietyt toimistosovellukset luovat niitä ja kuinka näitä rakenteita jäsennetään ja korjataan ohjelmallisesti käyttämällä Delphiä ja vankkoja PDF-kirjastoja.

PDF-ristiinviittaustaulukon kehitys

Objektien (fontit, kuvat, sivut) paikantamiseksi nopeasti jäsentämättä koko tiedostoa PDF käyttää ristiinviittaustaulukkoa (XRef). Aiemmissa PDF-määrityksissä (PDF 1.4 ja vanhemmat) tämä oli kirjaimellinen ASCII-tekstitaulukko tiedoston lopussa.

PDF 1.5:stä alkaen Adobe esitteli ristiinviittausvirrat (XRefStm), jotka pakkasivat ristiinviittaustiedot binäärivirraksi, mikä pienensi tiedostokokoja merkittävästi. Taaksepäin yhteensopivuuden ylläpitämiseksi vanhempien PDF-lukijoiden kanssa jotkin generaattorit alkoivat kuitenkin tuottaa hybridiviite-PDF-tiedostoja. Nämä tiedostot sisältävät sekä vanhan tyylin ASCII XRef -taulukon että uuden tyylin XRef-virran.

Hybridiviitteiden ongelma

Hybriditiedostot ovat teoreettisesti kelvollisia, mutta monet PDF-generaattorit (erityisesti vanhojen Office-pakettien "Tallenna PDF-muodossa" -liitännäiset) kirjoittavat ne väärin. Yleinen ohjelmointivirhe on väärän tavusiirtymän kirjoittaminen `startxref`-osoittimelle tai hajanaisten objektivirtojen luominen, joissa XRef-taulukko osoittaa väärään sukupolven numeroon.

Jos Delphi-sovelluksesi yrittää lukea huonosti muotoillun hybridi-PDF-tiedoston tiukkaa jäsennintä käyttäen, jäsennin epäonnistuu poikkeuksella "Vioittunut XRef-taulukko" (Corrupt XRef table) tai "Virheellinen objektinumero" (Invalid Object Number).

Hybridivaihtoehtojen käsittely PDFiumilla

PDFium-moottori (alunperin Foxitin kehittämä ja Googlen avoimen lähdekoodin julkaisema) sietää erittäin hyvin väärin muotoiltuja PDF-tiedostoja. Kun se havaitsee rikkinäisen XRef-taulukon, se skannaa tiedostoa automaattisesti taaksepäin EOF:stä paikantaakseen vaihtoehtoisen XRefStm:n.

Kun työskentelet PDFiumin kanssa Delphissä, sinun ei tarvitse jäsentää trailer-sanakirjoja manuaalisesti. Sinun tulisi kuitenkin tarkistaa rakenteelliset varoitukset, jotta voit varoittaa käyttäjää tai kirjata ongelman lokiin.

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;

PDF-tiedoston korjaaminen ja uudelleenrakentaminen

Jos työnkulkusi edellyttää PDF-tiedoston siirtämistä tiukempaan jatkojärjestelmään (kuten vanhempaan laitteisto-RIP:iin), sinun on "litistettävä" hybridirakenne. Luotettavin tapa korjata rikkinäinen hybridi-PDF Delphissä on ladata se suvaitsevaiseen moottoriin ja suorittaa Tallenna nimellä -toiminto. Tämä pakottaa jäsentimen rakentamaan muistissa olevasta objektipuusta puhtaan, yhtenäisen XRef-taulukon.

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

Hybridiviitteiden vioittumisen ymmärtäminen ja ennakointi varmistaa, että asiakirjojen käsittelyputkesi pysyvät joustavina, jopa vuosikymmeniä vanhojen perinteisten tiedostojen edessä.

Huomautus: PDFium Component VCL -komponentti tukee täysin hybridiviitteiden ratkaisemista ja automaattisia rakenteellisia korjauksia.