Как сформировать и прикрепить PDF-файл к документу в веб-клиенте 1С

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

При переходе с толстого или тонкого клиента на веб-клиент разработчики часто сталкиваются с проблемами при работе с файлами. Типичная задача — сформировать печатную форму в формате PDF и прикрепить ее к документу информационной базы. Однако привычные методы сохранения на локальный диск и вызовы синхронных функций в веб-клиенте вызывают ошибки или не дают результата. Разберем причины такого поведения и рассмотрим правильные варианты реализации данной задачи.

Почему попытка сохранения на диск в веб-клиенте приводит к ошибке

Проанализируем основные ограничения, с которыми сталкивается разработчик в веб-клиенте:

  1. Изоляция браузера (песочница): Веб-клиент работает внутри веб-браузера, который по соображениям безопасности полностью изолирован от файловой системы пользователя. Прямой доступ по путям вроде C:\temp\ из кода клиента невозможен.
  2. Недоступность каталогов: Функции КаталогВременныхФайлов() и ПолучитьИмяВременногоФайла() не поддерживаются в контексте клиента веб-клиента.
  3. Запрет синхронных вызовов: Даже при включенном свойстве конфигурации, разрешающем синхронные вызовы, браузерные ограничения не позволяют выполнять блокирующие файловые операции. Метод ПоместитьФайлы в веб-клиенте вызовет исключение.
  4. Лишний круг передачи данных: Если файл формируется программно внутри 1С и должен быть сохранен в базу, передавать его на клиентскую машину, сохранять на диск браузера, а затем загружать обратно на сервер абсолютно избыточно.

Основное решение: формирование и сохранение файла на сервере

Разберем по шагам правильную архитектуру решения. Так как табличный документ формируется на сервере и файл должен быть записан в базу данных, весь процесс должен происходить в серверном контексте без участия клиентской файловой системы.

Рассмотрим типовой алгоритм работы через временный файл на стороне сервера:

  1. Формируем ТабличныйДокумент в серверной процедуре.
  2. Получаем имя для временного файла на сервере с помощью ПолучитьИмяВременногоФайла("pdf").
  3. Сохраняем табличный документ в формате PDF на серверный диск.
  4. Считываем созданный файл в объект ДвоичныеДанные.
  5. Помещаем двоичные данные в реквизит объекта с типом ХранилищеЗначения или создаем новый элемент справочника присоединенных файлов.
  6. Удаляем созданный временный файл с диска сервера.

Посмотрим на пример серверного кода:


&НаСервере
Процедура СформироватьИПрикрепитьPDFКДокументу(СсылкаНаДокумент)
    
    // 1. Формируем табличный документ (печатную форму)
    ТабДок = Новый ТабличныйДокумент;
    // ... заполнение ТабДок данными ...
    
    // 2. Получаем временное имя файла на сервере
    ВременныйФайл = ПолучитьИмяВременногоФайла("pdf");
    
    Попытка
        // 3. Записываем табличный документ в формате PDF
        ТабДок.Записать(ВременныйФайл, ТипФайлаТабличногоДокумента.PDF);
        
        // 4. Получаем двоичные данные файла
        ДанныеФайла = Новый ДвоичныеДанные(ВременныйФайл);
        
        // 5. Записываем данные в реквизит объекта или создаем присоединенный файл
        ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        ДокументОбъект.ХранилищеПечатнойФормы = Новый ХранилищеЗначения(ДанныеФайла, Новый СжатиеДанных(9));
        ДокументОбъект.Записать();
        
    Исключение
        // В случае ошибки обязательно очищаем временный файл и передаем исключение
        УдалитьФайлы(ВременныйФайл);
        ВызватьИсключение;
    КонецПопытки;
    
    // 6. Удаляем временный файл с диска сервера
    УдалитьФайлы(ВременныйФайл);
    
КонецПроцедуры

Альтернативное решение: работа через поток в памяти (без временных файлов)

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

Посмотрим на пример реализации с использованием объекта ПотокВПамяти:


&НаСервере
Процедура СформироватьИСохранитьВПамяти(СсылкаНаДокумент)
    
    ТабДок = Новый ТабличныйДокумент;
    // ... заполнение ТабДок данными ...
    
    // Создаем поток в оперативной памяти
    Поток = Новый ПотокВПамяти;
    
    // Записываем PDF напрямую в поток
    ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.PDF);
    
    // Получаем двоичные данные и закрываем поток
    ДанныеФайла = Поток.ЗакрытьИПолучитьДвоичныеДанные();
    
    // Прикрепляем файл к объекту базы данных
    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    ДокументОбъект.ХранилищеПечатнойФормы = Новый ХранилищеЗначения(ДанныеФайла, Новый СжатиеДанных(9));
    ДокументОбъект.Записать();
    
КонецПроцедуры

Важные нюансы при формировании PDF на стороне сервера

Выясним несколько важных моментов, на которые следует обратить внимание при настройке серверной среды:

  1. Сервер под управлением Linux: Если сервер 1С работает на операционной системе Linux, для корректного формирования PDF-документов из ТабличныйДокумент в системе должны быть установлены графическая библиотека libgdiplus и базовые шрифты TrueType (например, пакет msttcorefonts). Без них вызов метода Записать завершится ошибкой.
  2. Передача файла пользователю для загрузки: Если после прикрепления файла к документу его также требуется отдать пользователю на скачивание в веб-клиенте, на сервере двоичные данные помещаются во временное хранилище через ПоместитьВоВременноеХранилище, а на клиенте вызывается асинхронный метод НачатьПолучениеФайлаССервера.
← На главную