Как передать табличный документ через HTTP-сервис в другую базу 1С?

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

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

Разберем основные практические способы решения этой задачи, выясним их преимущества и особенности реализации на платформе 1С:Предприятие 8.3.

Способ 1. Передача двоичных данных в формате MXL через поток в памяти (рекомендуемый)

Проанализируем наиболее быстрый и экономичный способ. Формат MXL является внутренним бинарным контейнером 1С, который штатно использует сжатие. Он полностью сохраняет все оформление документа, шрифты, ширину колонок и группировки. Начиная с версии платформы 8.3.9, нет необходимости сохранять файл на жесткий диск во временный каталог через ПолучитьИмяВременногоФайла() — всю операцию можно выполнить прямо в оперативной памяти с помощью объекта ПотокВПамяти.

Рассмотрим по шагам отправку табличного документа на стороне базы-источника. Нам потребуется записать табличный документ в поток, извлечь двоичные данные и поместить их в тело HTTP-запроса:


// База-отправитель: формируем и отправляем ТабличныйДокумент
ПотокПамяти = Новый ПотокВПамяти();
ТабДок.Записать(ПотокПамяти, ТипФайлаТабличногоДокумента.MXL);
ДвоичныеДанныеДокумента = ПотокПамяти.ЗакрытьИПолучитьДвоичныеДанные();

Соединение = Новый HTTPСоединение("server.domain", 80, "Логин", "Пароль");
Запрос = Новый HTTPЗапрос("/api/v1/mxl");
Запрос.Заголовки.Вставить("Content-Type", "application/octet-stream");
Запрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеДокумента);

Ответ = Соединение.ОтправитьДляОбработки(Запрос);

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


// База-получатель: метод HTTP-сервиса
Функция ПринятьТабличныйДокумент(Запрос)
    
    ДвоичныеДанныеТела = Запрос.ПолучитьТелоКакДвоичныеДанные();
    
    ПотокПамяти = Новый ПотокВПамяти(ДвоичныеДанныеТела);
    
    ПринятыйТабДок = Новый ТабличныйДокумент();
    ПринятыйТабДок.Прочитать(ПотокПамяти);
    ПотокПамяти.Закрыть();
    
    // ПринятыйТабДок готов к использованию (сохранению, показу или печати)
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.УстановитьТелоИзСтроки("Успешно получен", "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
    Возврат Ответ;
    
КонецФункции

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

Способ 2. Передача табличного документа в составе JSON через Base64

Рассмотрим ситуацию, когда табличный документ требуется передать не как отдельный файл, а вместе с сопутствующими метаданными (например, номер документа, дата, тип печатной формы, комментарий). В таком случае двоичные данные табличного документа кодируются в строку формата Base64 и помещаются в структуру JSON.

Посмотрим на пример упаковки документа в JSON на стороне клиента:


// Получаем двоичные данные MXL через поток в памяти
ПотокПамяти = Новый ПотокВПамяти();
ТабДок.Записать(ПотокПамяти, ТипФайлаТабличногоДокумента.MXL);
ДвоичныеДанныеMXL = ПотокПамяти.ЗакрытьИПолучитьДвоичныеДанные();

// Преобразуем в строку Base64
СтрокаBase64 = Base64Строка(ДвоичныеДанныеMXL);

// Формируем пакет данных JSON
Пакет = Новый Структура();
Пакет.Вставить("ИмяОтчета", "ПрайсЛист");
Пакет.Вставить("ДатаФормирования", ТекущаяДатаСессии());
Пакет.Вставить("ДанныеФайла", СтрокаBase64);

ЗаписьJSON = Новый ЗаписьJSON();
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Пакет);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Отправка запроса
Запрос = Новый HTTPЗапрос("/api/v1/report");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(СтрокаJSON);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

На стороне приемника разберем шаги десериализации JSON и восстановления документа:


Функция ОбработатьПакетJSON(Запрос)
    
    СтрокаJSON = Запрос.ПолучитьТелоКакСтроку();
    ЧтениеJSON = Новый ЧтениеJSON();
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    Пакет = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    // Извлекаем двоичные данные из строки Base64
    ДвоичныеДанныеMXL = Base64Значение(Пакет.ДанныеФайла);
    
    ПотокПамяти = Новый ПотокВПамяти(ДвоичныеДанныеMXL);
    ПринятыйТабДок = Новый ТабличныйДокумент();
    ПринятыйТабДок.Прочитать(ПотокПамяти);
    ПотокПамяти.Закрыть();
    
    Возврат Новый HTTPСервисОтвет(200);
    
КонецФункции

Важный момент: Кодирование в Base64 увеличивает объем передаваемых полезных данных примерно на 33%. Если передается только сам документ без метаданных, предпочтительнее использовать Способ 1.

Способ 3. Сериализация табличного документа через СериализаторXDTO в XML

Выясним, как работает сериализация объекта через СериализаторXDTO. Платформа 1С умеет сериализовать объект ТабличныйДокумент в XML и обратно без промежуточного сохранения в файл MXL.

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


// Сериализация документа в XML
ЗаписьXML = Новый ЗаписьXML();
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ТабДок);
СтрокаXML = ЗаписьXML.Закрыть();

// Отправка через HTTPЗапрос
Запрос = Новый HTTPЗапрос("/api/v1/xdto");
Запрос.Заголовки.Вставить("Content-Type", "application/xml; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(СтрокаXML);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

На стороне получателя достаточно прочитать XML обратно в объект ТабличныйДокумент:


Функция ПринятьXDTO(Запрос)
    
    СтрокаXML = Запрос.ПолучитьТелоКакСтроку();
    
    ЧтениеXML = Новый ЧтениеXML();
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    ПринятыйТабДок = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
    ЧтениеXML.Закрыть();
    
    Возврат Новый HTTPСервисОтвет(200);
    
КонецФункции

Ограничение метода: XML является текстовым форматом и подробно описывает каждую ячейку, строку и границу. Для объемных отчетов (тысячи строк) XML-представление может занимать в десятки раз больше места, чем сжатый MXL, что вызывает сильный расход оперативной памяти и задержки при сериализации.

Ограничения и важные нюансы реализации

При передаче табличных документов между серверами следует учитывать технические особенности инфраструктуры:

  1. Лимиты веб-серверов: Если отчет занимает много страниц, размер тела запроса может превысить установленные лимиты веб-сервера (IIS, Nginx или Apache), что вызовет ошибку 413 Payload Too Large. Необходимо заранее скорректировать директивы (например, client_max_body_size в Nginx или maxAllowedContentLength в IIS).
  2. Шрифты оформления: Если в документе использовались нестандартные шрифты, которых нет в операционной системе сервера-приемника, визуальное отображение отчета может сместиться.
  3. Альтернатива PDF: Если базе-приемнику требуется документ исключительно для архивного хранения или пересылки конечному пользователю без дальнейшего редактирования, практичнее сохранять его в ТипФайлаТабличногоДокумента.PDF и передавать готовый PDF-файл.
← На главную