Часто возникает задача встроить содержимое PDF-документа, прикрепленного к объекту в 1С, в печатную форму в виде изображения. Например, нужно вставить в один документ спецификацию товара, которая хранится как PDF. Прямая вставка двоичных данных PDF в макет не работает, так как система не распознает их как картинку. Разберем, как решить эту задачу с помощью внешних утилит или применяя работу с PDF файлами в 1С без внешних компонентов.
Выясним причину, почему это происходит. Платформа 1С умеет распознавать форматы изображений (такие как PNG, JPG, GIF, BMP) по их сигнатурам в начале файла и может работать с ними напрямую. PDF — это сложный документный формат, а не изображение. Поэтому, чтобы отобразить его как картинку, его нужно предварительно конвертировать.
Общий алгоритм действий для преобразования PDF в изображение выглядит следующим образом:
Рассмотрим два популярных способа реализации этого алгоритма с примерами кода.
ImageMagick — это мощный набор бесплатных программ для создания, редактирования и конвертации изображений. Он работает через командную строку и поддерживает огромное количество форматов. Подобный инструментарий также позволяет реализовать более сложные сценарии, такие как автоматизация добавления водяных знаков на фотографии — для этого подойдёт обработка автоматической вставки сканов печатей и подписей в печатные формы.
Посмотрим на пример функции, которая выполняет всю работу:
Функция КонвертироватьПрисоединенныйФайл_2_JPG(СсылкаПрисоединенныйФайл) Экспорт
// 1. Получаем двоичные данные файла
ДанныеФайла = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаПрисоединенныйФайл);
Если ДанныеФайла = Неопределено Тогда
Возврат Новый Массив;
КонецЕсли;
// 2. Создаем временный PDF-файл
ПолноеИмяФайлаPDF = ПолучитьИмяВременногоФайла("pdf");
Попытка
ДанныеФайла.Записать(ПолноеИмяФайлаPDF);
Исключение
// Обработка ошибки записи файла
Возврат Новый Массив;
КонецПопытки;
// 3. Вызываем конвертацию через ImageMagick
масФайлы = КонвертироватьФайл_PDF_TO_JPG(ПолноеИмяФайлаPDF);
// 4. Удаляем временный PDF
УдалитьФайлы(ПолноеИмяФайлаPDF);
Возврат масФайлы; // Возвращаем массив путей к созданным картинкам
КонецФункции
Функция КонвертироватьФайл_PDF_TO_JPG(ПолноеИмяФайлаPDF) Экспорт
пФайл = Новый Файл(ПолноеИмяФайлаPDF);
ПутьКФайлам = пФайл.Путь;
ИмяФайла = пФайл.ИмяБезРасширения;
// Формируем строку для командной строки
// Здесь ПутьImageMagic() - ваша функция, возвращающая путь к convert.exe
СтрокаВыполнить = ПутьImageMagic() + "convert -density 250 " + """" + ПолноеИмяФайлаPDF + """" + " -quality 120 " + """" + ПутьКФайлам + ИмяФайла + "-%02d.jpg" + """";
КодВозврата = 0;
// Запускаем процесс конвертации
ЗапуститьПриложение(СтрокаВыполнить, ПутьКФайлам, Истина, КодВозврата);
// Ищем созданные файлы по маске
МаскаДляПоиска = ИмяФайла + "-??.jpg";
массивИменJPG = НайтиФайлы(ПутьКФайлам, МаскаДляПоиска);
мас = Новый Массив;
Для каждого ФайлJPG из массивИменJPG Цикл
мас.Добавить(ФайлJPG.ПолноеИмя);
КонецЦикла;
Возврат мас;
КонецФункции
Разберем по шагам:
РаботаСФайлами.ДвоичныеДанныеФайла().ПолучитьИмяВременногоФайла("pdf") и записываем данные на диск методом ДвоичныеДанные.Записать().convert.exe из пакета ImageMagick.-density 250 задает разрешение картинки в DPI (точках на дюйм). Чем выше значение, тем качественнее, но и больше размер файла."-%02d.jpg" в имени выходного файла — это шаблон для многостраничных PDF. ImageMagick создаст файлы с именами имя-01.jpg, имя-02.jpg и так далее для каждой страницы.ЗапуститьПриложение(). Третий параметр Истина означает, что 1С будет ждать завершения работы конвертера.НайтиФайлы() и возвращаем массив с полными путями к ним.Ghostscript — это интерпретатор языка PostScript и формата PDF. Он часто используется как "движок" для других программ, но его можно вызывать и напрямую. Если ваша задача включает не только конвертацию, но и более глубокую обработку, обратите внимание на простое решение для сжатия и обработки PDF для 1С через Poppler.
Функция КонверторPDFtoJPG_двоичные(ДвоичныеДанныеФайла, УникальныйИдентификаторФормы=Неопределено) Экспорт
Путь_ВТ_Каталога = КаталогВременныхФайлов();
// ПутьККонвертеруPDFtoJPG() - ваша функция, возвращающая путь к gswin64c.exe
ПутьПриложенияКонвертор = ПутьККонвертеруPDFtoJPG();
ФайлКонвертированияPDF = Путь_ВТ_Каталога + СтрЗаменить(Новый УникальныйИдентификатор, "-", "") + ".pdf";
ФайлКонвертированияJPG = СтрЗаменить(ФайлКонвертированияPDF, ".pdf", "_p%02d.jpg");
ДвоичныеДанныеФайла.Записать(ФайлКонвертированияPDF);
// Формируем командную строку для Ghostscript
СтрокаЗапуска = """" + ПутьПриложенияКонвертор + """"
+ " -q -dSAFER -dBATCH -dNOPAUSE -sDEVICE=jpeg -r150 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sOutputFile="
+ """" + ФайлКонвертированияJPG + """" + " "
+ """" + ФайлКонвертированияPDF + """";
// Выполняем через WScript.Shell для большего контроля
WshShell = Новый COMОбъект("Wscript.Shell");
WshShell.Run(СтрокаЗапуска, 0, Истина); // 0 - скрыть окно, Истина - ждать завершения
// Ищем первый созданный файл
МассивФайлов = НайтиФайлы(Путь_ВТ_Каталога, СтрЗаменить(ФайлКонвертированияJPG, "%02d.jpg", "*.jpg"));
Если МассивФайлов.Количество() > 0 Тогда
// Читаем данные первой страницы и помещаем во временное хранилище
НовыеДвоичныеДанные = Новый ДвоичныеДанные(МассивФайлов[0].ПолноеИмя);
СсылкаНаХранилище = ПоместитьВоВременноеХранилище(НовыеДвоичныеДанные, УникальныйИдентификаторФормы);
// Очистка
УдалитьФайлы(ФайлКонвертированияPDF);
Для Каждого Файл Из МассивФайлов Цикл
УдалитьФайлы(Файл.ПолноеИмя);
КонецЦикла;
Возврат СсылкаНаХранилище;
Иначе
УдалитьФайлы(ФайлКонвертированияPDF);
Возврат Неопределено;
КонецЕсли;
КонецФункции
В этом примере для запуска используется COMОбъект("Wscript.Shell"). Его метод Run позволяет скрыть окно консоли (параметр 0) и дождаться завершения процесса (параметр Истина). Параметр -r150 аналогичен -density в ImageMagick и задает разрешение. После конвертации код находит результат, считывает его в двоичные данные, помещает во временное хранилище и удаляет за собой все временные файлы.
Помимо вызова внешних утилит, существуют и другие способы, которые могут быть более удобными или предоставлять расширенный функционал:
pdf2image в Python легко справляется с этой задачей и может быть вызвана из 1С.Важно помнить: какой бы способ вы ни выбрали, всегда предусматривайте обработку многостраничных документов и не забывайте удалять временные файлы после завершения операции.