В процессе автоматизации документооборота часто возникает задача программного анализа и работы с PDF файлами без внешних компонентов. Одной из самых востребованных операций является определение количества страниц в документе. Это необходимо для контроля корректности выгрузки, экспорта печатных форм, расчета стоимости печати или логики разделения файлов. Рассмотрим подробнее основные способы решения этой задачи, начиная от современных встроенных средств платформы и заканчивая низкоуровневым анализом данных.
Начиная с версии платформы 8.3.21, разработчикам стал доступен штатный механизм для работы с PDF. Это самый надежный и быстрый метод, не требующий установки стороннего программного обеспечения или регистрации COM-компонент. Проанализируем пример кода, который позволяет получить метаданные файла:
// Пример получения количества страниц через встроенный объект
ПутьКФайлу = "C:\temp\document.pdf";
ФайлPDF = Новый ДокументPDF;
Попытка
ФайлPDF.Прочитать(ПутьКФайлу);
КоличествоСтраниц = ФайлPDF.КоличествоСтраниц;
Сообщить("В файле обнаружено страниц: " + КоличествоСтраниц);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
КонецПопытки;
Разберем важные нюансы этого метода. При вызове метода Прочитать() платформа загружает структуру документа. Если файл защищен паролем на открытие, метод вызовет исключение. Также стоит учитывать, что при работе с очень большими файлами (сотни мегабайт) на сервере может возрасти потребление оперативной памяти, так как объект ДокументPDF оптимизирован для работы с содержимым.
Если ваша информационная база работает на версии платформы ниже 8.3.21, мы можем прибегнуть к анализу внутреннего содержимого PDF-файла. Структура PDF представляет собой иерархию объектов, для разбора которых могут потребоваться инструменты для работы с потоками и двоичными данными. Количество страниц обычно хранится в объекте типа /Pages в атрибуте /Count. Проанализируем ситуацию, когда нам нужно быстро получить число без полной загрузки документа в память.
Рассмотрим по шагам алгоритм реализации:
VBScript.RegExp для поиска шаблона /Count\s+(\d+).
// Поиск количества страниц через регулярные выражения
Функция ПолучитьКоличествоСтраницPDF(ПутьКФайлу)
ТекстДокумента = Новый ТекстовыйДокумент;
// Используем кодировку, которая не искажает бинарные данные
ТекстДокумента.Прочитать(ПутьКФайлу, "ISO-8859-1");
ПолныйТекст = ТекстДокумента.ПолучитьТекст();
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
// Ищем вхождение /Count и следующее за ним число
RegExp.Pattern = "/Count\s+(\d+)";
Matches = RegExp.Execute(ПолныйТекст);
Если Matches.Count > 0 Тогда
// Обычно последнее вхождение /Count в структуре файла является верным
Возврат Число(Matches.Item(Matches.Count - 1).SubMatches.Item(0));
КонецЕсли;
Возврат 0;
КонецФункции
Важно помнить, что в некоторых сложных PDF-файлах (например, со встроенными другими PDF) вхождений /Count может быть несколько. В таких случаях мы рекомендуем проверять корректность данных или использовать более сложные регулярные выражения для поиска объекта /Type /Pages.
Выясним причину, по которой у многих разработчиков возникают сложности с внешними утилитами вроде pdfinfo.exe. Основная проблема — перенаправление вывода в файл через символ >. При запуске через ЗапуститьПриложение операционная система может не распознать операторы командной строки. Вместо использования стороннего ПО, мы можем воспользоваться встроенным PowerShell.
Рассмотрим пример команды, которую можно вызвать из 1С:
КомандаPS = "powershell -command ""$content = Get-Content 'C:\temp\file.pdf' -Raw; if ($content -match '/Count\s+(\d+)') { $matches[1] }""";
// Используем WScript.Shell для получения результата без временных файлов
Shell = Новый COMОбъект("WScript.Shell");
Exec = Shell.Exec(КомандаPS);
Результат = Exec.StdOut.ReadAll();
Сообщить("Страниц: " + СокрЛП(Результат));
Этот способ хорош тем, что не требует наличия дополнительных исполняемых файлов в каталоге программы и обходит ограничения прав доступа на создание временных .txt файлов.
Если на сервере или рабочей станции установлен Adobe Acrobat (не Reader) или специализированные библиотеки типа PDFCreator, мы можем обратиться к их API. Это наиболее надежный метод для работы со специфическими форматами PDF (например, PDF/A или зашифрованными файлами).
Посмотрим на пример работы с гипотетической библиотекой редактирования:
Попытка
РедакторPDF = Новый COMОбъект("PDF.Document.Object"); // Имя объекта зависит от установленного ПО
РедакторPDF.LoadFromFile(ИмяФайла);
ВсегоСтраниц = РедакторPDF.PageCount;
Сообщить(ВсегоСтраниц);
Исключение
Сообщить("Библиотека не зарегистрирована");
КонецПопытки;
Проанализируем еще один интересный способ, который часто упускают из виду. Операционная система Windows умеет извлекать метаданные файлов через свойства Проводника. Если в системе установлен обработчик PDF, информацию можно получить через Shell.Application.
Shell = Новый COMОбъект("Shell.Application");
Folder = Shell.NameSpace("C:\temp");
File = Folder.ParseName("document.pdf");
// Индекс 158 часто соответствует количеству страниц, но может меняться от версии ОС
КоличествоСтраниц = Folder.GetDetailsOf(File, 158);
Этот метод работает очень быстро, так как не читает весь файл целиком, а обращается только к расширенным свойствам файловой системы. Однако его существенный недостаток — зависимость индекса свойства (158) от версии Windows и установленного софта.
Разберем ситуацию, когда определение количества страниц требуется в веб-клиенте. Поскольку прямой доступ к файловой системе в браузере ограничен, мы рекомендуем следующий алгоритм:
НачатьПомещениеФайлаНаСервер.ДокументPDF для 8.3.21).Если необходимо реализовать проверку без передачи файла на сервер, это можно сделать только с помощью встраивания JavaScript в поле HTML-документа, используя библиотеку PDF.js. Однако для большинства бизнес-задач серверная обработка является более предпочтительной и простой в реализации.
Подводя итог, можно сказать: если ваша версия платформы позволяет использовать ДокументPDF — используйте его как основной стандарт. В случае работы на старых версиях, оптимальным выбором будет поиск по тегу /Count через регулярные выражения или использование PowerShell для получения точных данных без регистрации внешних компонент. Помните о проверке прав доступа к файлам и всегда обрабатывайте возможные ошибки чтения внутри блока Попытка...Исключение.