Під час розробки корпоративних рішень для роботи з документами ви неминуче зіткнетеся з PDF-файлами, створеними за допомогою безлічі різних інструментів: від висококласного програмного забезпечення Adobe до помилкових бібліотек з відкритим вихідним кодом або драйверів віртуальних принтерів. Однією з найвідоміших структурних проблем, з якими ви зіткнетеся, є гібридний PDF-файл (hybrid-reference).
У цій статті ми пояснимо, що таке гібридні посилання, чому певні офісні програми створюють їх, а також як програмно аналізувати та виправляти ці структури за допомогою Delphi та надійних бібліотек PDF.
Еволюція таблиці перехресних посилань PDF
Щоб швидко знаходити об'єкти (шрифти, зображення, сторінки) без синтаксичного аналізу всього файлу, PDF використовує таблицю перехресних посилань (XRef). У попередніх специфікаціях PDF (PDF 1.4 і старіших) це була буквальна текстова таблиця ASCII в кінці файлу.
Починаючи з PDF 1.5, компанія Adobe представила потоки перехресних посилань (XRefStm), які стискали дані перехресних посилань у двійковий потік, значно зменшуючи розміри файлів. Однак для зворотної сумісності зі старішими програмами для читання PDF деякі генератори почали створювати гібридні PDF-файли (Hybrid-Reference PDFs). Ці файли містять як таблицю XRef у старому стилі ASCII, так і потік XRef у новому стилі.
Проблема з гібридними посиланнями
Гібридні файли теоретично є дійсними, але багато генераторів PDF (особливо застарілі плагіни "Зберегти як PDF" у старих офісних пакетах) записують їх неправильно. Поширеною помилкою є запис неправильного зміщення байтів для покажчика `startxref` або створення розрізнених потоків об'єктів, де таблиця XRef вказує на неправильний номер покоління.
Якщо ваш додаток Delphi намагається прочитати погано сформований гібридний PDF-файл за допомогою суворого аналізатора, аналізатор видасть виняток "Corrupt XRef table" або "Invalid Object Number".
Обробка гібридних резервних варіантів за допомогою PDFium
Рушій PDFium (спочатку розроблений компанією Foxit і відкритий Google) є дуже толерантним до неправильно сформованих PDF-файлів. Коли він виявляє пошкоджену таблицю XRef, він автоматично сканує файл у зворотному напрямку від кінця файлу (EOF), щоб знайти альтернативний XRefStm.
У Delphi при роботі з PDFium вам не потрібно вручну аналізувати словники трейлера. Однак вам слід перевіряти наявність структурних попереджень, щоб мати змогу попередити користувача або зареєструвати проблему.
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-файлу
Якщо ваш робочий процес вимагає передачі PDF-файлу до більш суворої наступної системи (наприклад, старішого апаратного RIP), вам потрібно "згладити" гібридну структуру. Найнадійніший спосіб виправити пошкоджений гібридний PDF-файл у Delphi: завантажити його в толерантний рушій і виконати операцію "Зберегти як". Це змушує аналізатор відновити чисту уніфіковану таблицю 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;
Розуміння та передбачення пошкоджень гібридних посилань гарантує, що ваші конвеєри обробки документів залишатимуться стійкими навіть при зіткненні із застарілими файлами десятирічної давності.
Примітка: Вирішення гібридних посилань та автоматичне відновлення структури повністю підтримуються компонентом PDFium Component.