Pri razvoju dokumentnih rešitev za podjetja boste neizogibno naleteli na PDF datoteke, ki jih ustvari ogromno različnih orodij, od vrhunske programske opreme Adobe do hroščate odprtokodne knjižnice ali virtualnih gonilnikov tiskalnikov. Ena izmed najbolj zloglasnih strukturnih težav, s katerimi se boste soočili, je "hibridna referenca" (hybrid-reference) PDF datoteke.
V tem članku bomo pojasnili, kaj so hibridne reference, zakaj jih določene Office aplikacije ustvarjajo ter kako programsko razčleniti in popraviti te strukture z uporabo Delphija in robustnih PDF knjižnic.
Evolucija tabele navzkrižnih referenc PDF
Za hitro iskanje objektov (pisav, slik, strani) brez razčlenjevanja celotne datoteke PDF uporablja tabelo navzkrižnih referenc (Cross-Reference Table - XRef). V starejših specifikacijah PDF (PDF 1.4 in starejše) je bila to dobesedna tabela z besedilom ASCII na koncu datoteke.
Začenši s PDF 1.5 je Adobe predstavil tokove navzkrižnih referenc (Cross-Reference Streams - XRefStm), ki so stisnili podatke navzkrižnih referenc v binarni tok in s tem znatno zmanjšali velikost datotek. Kljub temu so za združljivost za nazaj s starejšimi bralniki PDF nekateri generatorji začeli ustvarjati PDF datoteke s hibridnimi referencami. Te datoteke vsebujejo tako staro tabelo XRef v formatu ASCII kot nov tok XRef.
Težava s hibridnimi referencami
Hibridne datoteke so teoretično veljavne, vendar jih mnogi generatorji PDF (zlasti starejši vtičniki "Shrani kot PDF" v starejših pisarniških paketih) zapišejo nepravilno. Pogost hrošč je pisanje napačnega bajtnega odmika za kazalec `startxref` ali ustvarjanje nepovezanih tokov objektov, kjer tabela XRef kaže na napačno številko generacije.
Če vaša Delphi aplikacija poskuša prebrati slabo oblikovano hibridno datoteko PDF s strogim razčlenjevalnikom, bo razčlenjevalnik odpovedal z izjemo "Corrupt XRef table" (Poškodovana tabela XRef) ali "Invalid Object Number" (Neveljavna številka objekta).
Obravnavanje hibridnih napak s PDFium
Mehanizem PDFium (ki ga je prvotno razvil Foxit in je zdaj odprtokoden pod okriljem Googla) je zelo toleranten do slabo oblikovanih PDF datotek. Ko zazna poškodovano tabelo XRef, samodejno preišče datoteko nazaj od konca (EOF), da najde alternativni XRefStm.
V Delphiju vam pri delu s PDFium ni treba ročno razčlenjevati slovarjev trailerja. Vendar pa bi morali preveriti strukturna opozorila, da lahko opozorite uporabnika ali zabeležite težavo.
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 in obnova PDF dokumenta
Če vaš delovni proces zahteva posredovanje PDF datoteke v strožji sistem v nadaljevanju (kot je starejši strojni RIP), morate "sploščiti" (flatten) hibridno strukturo. Najbolj zanesljiv način za popravilo poškodovanega hibridnega PDF dokumenta v Delphiju je nalaganje v toleranten mehanizem in izvedba operacije "Shrani kot" (Save-As). To prisili razčlenjevalnik, da iz drevesa objektov v pomnilniku zgradi čisto, enotno tabelo XRef.
// 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;
Razumevanje in predvidevanje poškodb hibridnih referenc zagotavlja, da vaši cevovodi za obdelavo dokumentov ostanejo odporni, tudi ko se soočijo z desetletja starimi datotekami.
Opomba: Razreševanje hibridnih referenc in samodejna strukturna popravila so v celoti podprta v komponenti PDFium Component.