Как отдать отчет из 1С через HTTP-сервис

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

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

Базовый принцип: сохранение отчета в HTML через временный файл

Проанализируем классический вариант, при котором табличный документ генерируется на стороне сервера, сохраняется во временный файл в формате HTML5, считывается и передается в браузер в теле HTTP-ответа.

Рассмотрим реализацию метода сохранения табличного документа в текстовую строку:


ИмяВремФайла = ПолучитьИмяВременногоФайла("html");
ТаблДокСОтчетом.Записать(ИмяВремФайла, ТипФайлаТабличногоДокумента.HTML5);

ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.Прочитать(ИмяВремФайла, КодировкаТекста.UTF8);
ТекстОтчетаHTML = ТекстДок.ПолучитьТекст();

УдалитьФайлы(ИмяВремФайла);

Полученный текст разметки передается в обработчик сервиса. Рассмотрим структуру типового метода GET для HTTP-сервиса:


Функция ОтчетыGet(Запрос)

    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-Type", "text/html; charset=utf-8");
    
    // Формируем отчет в переменную ТаблДок
    ТаблДок = СформироватьНужныйОтчет();
    
    ИмяВремФайла = ПолучитьИмяВременногоФайла("html");
    ТаблДок.Записать(ИмяВремФайла, ТипФайлаТабличногоДокумента.HTML5);
    
    ТекстДок = Новый ТекстовыйДокумент;
    ТекстДок.Прочитать(ИмяВремФайла, КодировкаТекста.UTF8);
    ТекстОтчетаHTML = ТекстДок.ПолучитьТекст();
    
    Попытка
        УдалитьФайлы(ИмяВремФайла);
    Исключение
    КонецПопытки;
    
    Ответ.УстановитьТелоИзСтроки(ТекстОтчетаHTML, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    Возврат Ответ;

КонецФункции

Оптимизация: передача отчета через поток в оперативной памяти

Постоянная запись временных файлов на жесткий диск и их последующее чтение создают дополнительную нагрузку на серверную операционную систему и замедляют обработку запросов. Избавимся от дисковых операций ввода-вывода (I/O) с помощью объекта ПотокВПамяти. Метод Записать() объекта ТабличныйДокумент умеет выгружать данные напрямую в поток.

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


Функция ОтчетыПотокGet(Запрос)

    ТаблДок = СформироватьНужныйОтчет();
    
    Поток = Новый ПотокВПамяти;
    ТаблДок.Записать(Поток, ТипФайлаТабличногоДокумента.HTML5);
    ДвоичныеДанныеОтчета = Поток.ЗакрытьИПолучитьДвоичныеДанные();
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-Type", "text/html; charset=utf-8");
    Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеОтчета);
    
    Возврат Ответ;

КонецФункции

Встраивание отчета на существующую веб-страницу

Если сгенерированный HTML-документ необходимо внедрить внутрь страницы сайта, а не открывать в отдельной вкладке, могут возникнуть конфликты встроенных CSS-стилей платформы со стилями сайта. Выделим основные пути решения этой задачи:

  1. Изоляция стилей в отдельный контейнер: оборачиваем сформированный фрагмент в отдельный тег div со своим классом и изолируем правила CSS.
  2. Использование фреймов: встраиваем ссылку на вызов HTTP-сервиса в тег iframe. В этом случае браузер изолирует стили и скрипты отчета от основного портала.
  3. Перенос стилей: программно извлекаем содержимое блока style из выгруженного отчета и переносим его в блок head главной страницы.

Передача отчета в формате PDF

При выгрузке отчетов с диаграммами или логотипами экспорт в HTML имеет существенный недостаток: платформа создает отдельные графические файлы и ссылается на них относительными путями, из-за чего браузер не сможет их отобразить без дополнительной передачи картинок. Кроме того, форматирование HTML-таблиц может искажаться в зависимости от движка браузера.

Проанализируем альтернативный и надежный способ — отдачу отчета в формате PDF:


Функция ОтчетPDFGet(Запрос)

    ТаблДок = СформироватьНужныйОтчет();
    
    Поток = Новый ПотокВПамяти;
    ТаблДок.Записать(Поток, ТипФайлаТабличногоДокумента.PDF);
    ДвоичныеДанныеPDF = Поток.ЗакрытьИПолучитьДвоичныеДанные();
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-Type", "application/pdf");
    Ответ.Заголовки.Вставить("Content-Disposition", "inline; filename=""report.pdf""");
    Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеPDF);
    
    Возврат Ответ;

КонецФункции

Заголовок Content-Disposition со значением inline указывает браузеру, что документ нужно открыть во встроенном средстве просмотра PDF, а не скачивать на диск.

Особенности программного формирования отчетов на СКД

Обработчик HTTP-сервиса всегда исполняется в серверном контексте без клиентских окон и возможности открыть форму отчета интерактивно. Если отчет спроектирован на базе Системы компоновки данных, его инициализация выполняется программно:

  1. Получаем схему компоновки через метод ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных") нужного объекта конфигурации.
  2. Инициализируем настройки через КомпоновщикНастроек, программно заполняем необходимые параметры и значения отборов.
  3. Выполняем компоновку макета с помощью объекта КомпоновщикМакета.
  4. Инициализируем ПроцессорКомпоновкиДанных и последовательно выводим результат в ТабличныйДокумент с использованием объекта ПроцессорВыводаТабличногоДокументаВТабличныйДокумент.

Длительные отчеты и предотвращение таймаутов

Веб-серверы (Apache, IIS, Nginx) принудительно обрывают входящее соединение при превышении времени ожидания (обычно от 30 до 60 секунд), возвращая клиенту ошибку 504 Gateway Timeout. Если формирование отчета занимает много времени, синхронный вызов приведет к сбою.

Для тяжелых отчетов применяем асинхронную схему:

  1. Старт формирования (метод POST): HTTP-сервис запускает фоновое задание через ФоновыеЗадания.Выполнить(). Внутри задания отчет формируется и помещается во временное хранилище. Сервис сразу возвращает клиенту код 202 Accepted и строковый идентификатор фонового задания.
  2. Опрос состояния (метод GET): клиент с интервалом в несколько секунд опрашивает сервис, передавая полученный идентификатор. Сервис проверяет статус через ФоновыеЗадания.НайтиПоУникальномуИдентификатору().
  3. Выдача результата: после завершения задания сервис считывает готовый результат через ПолучитьИзВременногоХранилища() и отдает клиенту итоговый файл.

Также помним о настройке файла публикации default.vrd: для высоконагруженных сценариев важно настраивать пул сеансов, чтобы платформа не тратила ресурсы на повторный запуск сеанса при каждом входящем HTTP-запросе.

← На главную