Как сохранить печатную форму 1С в PDF как изображение для защиты факсимиле и текста

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При отправке клиентам печатных форм (например, счетов на оплату, актов или накладных) компании часто используют факсимиле — графические изображения печати организации и подписей ответственных лиц. Стандартный механизм сохранения табличного документа в формат PDF, встроенный в платформу 1С:Предприятие, формирует векторный документ. В таком файле текстовые слои остаются доступными для выделения и копирования, а картинки подписей и печатей накладываются отдельными графическими объектами с прозрачным фоном.

Это создает серьезную угрозу информационной безопасности: любой получатель может открыть полученный PDF-файл в векторном редакторе (таком как Adobe Illustrator, CorelDraw) или даже в обычном PDF-редакторе и легко извлечь изображение печати и подписи в исходном качестве. В дальнейшем злоумышленники могут использовать это факсимиле для фальсификации других документов. В этой статье мы подробно разберем, как решить эту проблему и сохранить печатную форму в PDF так, чтобы она представляла собой единую «плоскую» картинку, исключающую извлечение отдельных элементов.

Почему стандартное сохранение в 1С не решает задачу защиты?

Когда мы вызываем стандартный метод ТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.PDF), платформа преобразует ячейки, текст и рисунки табличного документа в соответствующие векторные и растровые объекты спецификации PDF. Текст сохраняется в виде шрифтовых последовательностей, а факсимиле — в виде внедренного бинарного объекта. Защитить такой документ от копирования штатными средствами старых версий платформы невозможно.

Для создания гарантированно безопасного документа нам необходимо провести растеризацию — процесс преобразования векторного описания страниц в растровое изображение (набор пикселей). Рассмотрим основные способы реализации этой задачи на платформе 1С:Предприятие.

Способ 1. Программная защита PDF средствами платформы (для версий 8.3.21+)

Если перед нами не стоит жесткое требование превратить весь документ именно в картинку, а нужно лишь заблокировать стандартные действия пользователя (копирование текста, извлечение графики, редактирование), мы можем воспользоваться новыми возможностями платформы 1С, появившимися в версии 8.3.21. С помощью объекта ЗаписьPDF можно программно установить ограничения на итоговый файл.

Проанализируем пример кода, устанавливающий защиту на создаваемый PDF-документ:


// Создаем объект защиты и настраиваем ограничения
ПараметрыЗащиты = Новый ПараметрыЗащитыPDF;
ПараметрыЗащиты.ЗапретитьКопированиеТекста = Истина;
ПараметрыЗащиты.ЗапретитьРедактирование = Истина;
ПараметрыЗащиты.ЗапретитьПечать = Ложь; // Разрешаем пользователю только распечатать документ

// Устанавливаем пароль владельца, который необходим для изменения прав доступа к файлу
ПараметрыЗащиты.УстановитьПарольВладельца("СложныйПарольАдминистратора123!");

// Инициируем запись документа с параметрами защиты
ЗаписьPDF = Новый ЗаписьPDF;
ЗаписьPDF.Открыть(ПутьКФайлуPDF, ПараметрыЗащиты);
ЗаписьPDF.Записать(ТабличныйДокумент);
ЗаписьPDF.Закрыть();

Преимущества: Высокая скорость работы, отсутствие необходимости в стороннем программном обеспечении на сервере, файл сохраняет небольшой размер.

Недостатки: Слои физически остаются разделенными. Опытный пользователь или специализированные утилиты по обходу защиты PDF могут извлечь графику факсимиле.

Способ 2. Растеризация на сервере с помощью внешних утилит (ImageMagick / Poppler)

Для создания абсолютно надежного «плоского» PDF-файла, в котором все элементы слиты в единую картинку, мы можем применить двухэтапный процесс на сервере:

  1. Сохранить исходный документ во временный векторный PDF стандартным методом 1С.
  2. Передать этот файл консольной утилите, которая переведет каждую страницу в растровый формат (например, PNG или JPEG), а затем соберет их обратно в единый PDF-документ.

В качестве серверного инструмента отлично подходит пакет ImageMagick (совместно с Ghostscript) или утилита pdftoppm (из пакета Poppler-utils), которая работает быстро и стабильно как под Windows, так и под Linux.

Рассмотрим пример реализации на сервере под управлением Windows с использованием утилиты pdftoppm для извлечения страниц и последующей сборки через встроенные механизмы 1С:


// Шаг 1. Сохраняем исходный табличный документ во временный векторный PDF
ВременныйВекторныйPDF = ПолучитьИмяВременногоФайла("pdf");
ТабличныйДокумент.Записать(ВременныйВекторныйPDF, ТипФайлаТабличногоДокумента.PDF);

// Шаг 2. Создаем временную директорию для хранения растровых страниц
КаталогКартинок = ПолучитьИмяВременногоФайла("");
СоздатьКаталог(КаталогКартинок);

// Шаг 3. Запускаем утилиту pdftoppm для конвертации страниц PDF в PNG-изображения
// Параметр "-r 150" задает разрешение в DPI (150-200 вполне достаточно для документов)
ПутьКPdftoppm = "C:\Program Files\poppler\bin\pdftoppm.exe";
ПараметрыЗапуска = "-png -r 150 """ + ВременныйВекторныйPDF + """ """ + КаталогКартинок + "\page""";

ЗапуститьПриложение(ПутьКPdftoppm + " " + ПараметрыЗапуска, , Истина); // Ожидаем завершения процесса

// Шаг 4. Собираем картинки обратно в "плоский" табличный документ силами 1С
ТабДокПлоский = Новый ТабличныйДокумент;
ТабДокПлоский.ПолеСверху = 0;
ТабДокПлоский.ПолеСнизу = 0;
ТабДокПлоский.ПолеСлева = 0;
ТабДокПлоский.ПолеСправа = 0;

НайденныеФайлы = НайтиФайлы(КаталогКартинок, "page-*.png");
Счетчик = 0;

Для Каждого ФайлСтраницы Из НайденныеФайлы Цикл
    Счетчик = Счетчик + 1;
    
    // Если страница не первая, принудительно вставляем разрыв
    Если Счетчик > 1 Тогда
        ТабДокПлоский.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЕсли;
    
    // Создаем рисунок и загружаем в него растровую страницу
    Рисунок = ТабДокПлоский.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
    Рисунок.Картинка = Новый Картинка(ФайлСтраницы.ПолноеИмя);
    
    // Позиционируем рисунок на всю страницу А4
    Рисунок.Верх = 0;
    Рисунок.Лево = 0;
    Рисунок.Ширина = 210;  // Ширина А4 в миллиметрах
    Рисунок.Высота = 297; // Высота А4 в миллиметрах
    Рисунок.РазмернаяКартинка = РазмернаяКартинка.РеальныйРазмер;
КонецЦикла;

// Шаг 5. Записываем итоговый защищенный PDF
ТабДокПлоский.Записать(ПутьКВыходномуФайлуPDF, ТипФайлаТабличногоДокумента.PDF);

// Очищаем временные файлы
УдалитьФайлы(ВременныйВекторныйPDF);
УдалитьФайлы(КаталогКартинок);

Важный нюанс: Обратите внимание на установку полей результирующего табличного документа в значение 0. Это необходимо для того, чтобы внедренные растровые страницы А4 выводились ровно по границам печати и не масштабировались повторно платформой при конвертации.

Способ 3. Использование Python-скрипта на сервере 1С

В современных ИТ-инфраструктурах серверы 1С часто функционируют под управлением операционных систем семейства Linux. В таких условиях удобно использовать легковесные скрипты на языке Python, которые могут быть вызваны из 1С. Для преобразования векторного PDF в растровый можно применить высокопроизводительную библиотеку PyMuPDF (также известную как fitz).

Сначала посмотрим на код самого скрипта Python (rasterize.py):


import sys
import fitz  # Импортируем PyMuPDF

def rasterize_pdf(input_path, output_path, dpi=150):
    # Открываем исходный векторный документ
    doc = fitz.open(input_path)
    out_doc = fitz.open()
    
    for page in doc:
        # Рендерим страницу в растровое изображение с заданным DPI
        pix = page.get_pixmap(dpi=dpi)
        # Превращаем картинку в байты формата PNG
        img_data = pix.tobytes("png")
        
        # Создаем временный одностраничный PDF из картинки и добавляем его в итоговый документ
        img_doc = fitz.open("pdf", pix.pdf_bytes())
        out_doc.insert_pdf(img_doc)
        
    # Сохраняем оптимизированный "плоский" файл
    out_doc.save(output_path)
    out_doc.close()
    doc.close()

if __name__ == "__main__":
    if len(sys.argv) > 2:
        rasterize_pdf(sys.argv[1], sys.argv[2])

Теперь разберем, как вызвать этот скрипт непосредственно из кода 1С:


// Формируем пути к файлам
ВходнойФайл = ПолучитьИмяВременногоФайла("pdf");
ВыходнойФайл = "C:\Saves\Invoice_Protected.pdf";

// Записываем исходный макет
ТабличныйДокумент.Записать(ВходнойФайл, ТипФайлаТабличногоДокумента.PDF);

// Формируем команду запуска скрипта Python
ПутьКСкрипту = "C:\PythonScripts\rasterize.py";
КомандаЗапуска = "python """ + ПутьКСкрипту + """ """ + ВходнойФайл + """ """ + ВыходнойФайл + """";

// Выполняем команду на сервере в режиме ожидания
ЗапуститьПриложение(КомандаЗапуска, , Истина);

// Удаляем временный исходный файл
УдалитьФайлы(ВходнойФайл);

Этот метод работает быстро, кроссплатформенно и не требует создания множества временных файлов изображений на диске, так как вся обработка и конвертация страниц происходит в оперативной памяти сервера.

Резюме и рекомендации

Мы проанализировали различные варианты защиты документов при сохранении в PDF. Выбор конкретного инструмента зависит от ваших требований к безопасности и окружения:

← На главную