Как правильно организовать формирование XML-файла на сервере и его сохранение на клиенте в 1С

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

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

Разбор проблемы клиент-серверного взаимодействия

Проблема заключается в том, что процедура формирования XML обычно располагается в общем модуле с установленным флагом Сервер. Когда мы пытаемся вызвать сохранение файла напрямую из этого модуля, платформа выдает ошибку, так как сервер не «видит» локальные диски пользователя. Нам необходимо построить мост между сервером, где рождаются данные, и клиентом, где эти данные превращаются в файл на диске.

Проанализируем основные этапы решения этой задачи:

  1. Подготовка данных на стороне сервера.
  2. Помещение готовых данных во Временное хранилище.
  3. Передача адреса хранилища на клиент.
  4. Интерактивное сохранение файла пользователем.

Использование временного хранилища как универсального буфера

Рассмотрим наиболее надежный и проверенный способ — использование механизма временного хранилища. Вместо того чтобы пытаться передать XML как огромную строку (что неэффективно и может привести к проблемам с кодировкой), мы будем оперировать объектом ДвоичныеДанные.

Выясним, как это реализовать в коде серверного модуля. Допустим, у нас есть процедура в серверном общем модуле, которая формирует данные:


Функция СформироватьXMLНаСервере(ПараметрыОтчета) Экспорт
    // Создаем временное имя файла на сервере
    ИмяФайла = ПолучитьИмяВременногоФайла("xml");
    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла, "UTF-8");
    
    // Здесь происходит логика заполнения XML
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    ЗаписьXML.ЗаписатьНачалоЭлемента("Root");
    // ... заполнение данными ...
    ЗаписьXML.ЗаписатьКонецЭлемента();
    ЗаписьXML.Закрыть();
    
    // Преобразуем файл в двоичные данные
    ДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);
    
    // Помещаем во временное хранилище и получаем адрес
    АдресХранилища = ПоместитьВоВременноеХранилище(ДанныеФайла);
    
    // Удаляем временный файл с диска сервера
    УдалитьФайлы(ИмяФайла);
    
    Возврат АдресХранилища;
КонецФункции

Важный момент: использование ДвоичныеДанные позволяет избежать проблем с кодировкой и BOM-метками, которые часто возникают при передаче обычного текста между контекстами.

Оптимизация работы через ПотокВПамяти

Разберем более современный подход, доступный в новых версиях платформы. Мы можем вообще отказаться от записи временного файла на диск сервера, используя ПотокВПамяти. Это значительно ускоряет работу и избавляет от лишних операций ввода-вывода (I/O).

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


Функция СформироватьXMLВПамяти() Экспорт
    Поток = Новый ПотокВПамяти();
    ЗаписьXML = Новый ЗаписьXML;
    
    // Открываем запись прямо в поток памяти
    ЗаписьXML.ОткрытьПоток(Поток, "UTF-8");
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    // Логика формирования...
    ЗаписьXML.Закрыть();
    
    // Получаем двоичные данные из потока
    Данные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
    Возврат ПоместитьВоВременноеХранилище(Данные);
КонецФункции

Асинхронное сохранение файла на стороне клиента

Теперь проанализируем, что происходит на клиенте. Согласно современным стандартам разработки (интерфейс «Такси»), взаимодействие с файловой системой должно быть асинхронным. Это гарантирует, что интерфейс программы не «зависнет» во время ожидания ответа от системы или выбора пользователем пути сохранения.

Рассмотрим, как правильно вызвать сохранение, если мы используем платформу 8.3.18 и выше с поддержкой Async/Await (Ждать):


&НаКлиенте
Асинх Процедура СформироватьИСохранитьФайл(Команда)
    
    // Шаг 1: Вызов сервера для получения данных
    АдресФайла = СформироватьXMLНаСервереНаСервере();
    
    // Шаг 2: Настройка параметров сохранения
    ПараметрыСохранения = Новый ПараметрыДиалогаПолученияФайлов;
    ПараметрыСохранения.Заголовок = "Выберите куда сохранить выгрузку XML";
    ПараметрыСохранения.Фильтр = "Файлы XML (*.xml)|*.xml";
    
    // Шаг 3: Асинхронный вызов диалога и скачивания
    ОписаниеФайла = Новый ОписаниеПередаваемогоФайла("Выгрузка.xml", АдресФайла);
    МассивФайлов = Новый Массив;
    МассивФайлов.Добавить(ОписаниеФайла);
    
    Ждать ПолучитьФайлыССервераАсинх(МассивФайлов, ПараметрыСохранения);
    
    ПоказатьОповещениеПользователя("Готово", , "Файл успешно сохранен");
    
КонецПроцедуры

Почему это лучше, чем передача строки?

Проанализируем технические детали. В обсуждении на форуме упоминалось, что XML — это просто текст, и его можно передать строкой. Однако опытные разработчики возражают, и вот почему:

  1. Объем данных: Объект Строка в 1С при передаче между сервером и клиентом не сжимается автоматически. Если ваш XML весит 10-20 Мб, передача строки создаст серьезную нагрузку на сеть.
  2. Сериализация: ДвоичныеДанные при помещении во временное хранилище могут быть оптимизированы платформой.
  3. Кодировки: При записи текста в файл на клиенте из строковой переменной легко ошибиться в кодировке. Работая с ДвоичныеДанные, вы сохраняете байт-в-байт то, что сформировал сервер.

Использование Библиотеки Стандартных Подсистем (БСП)

Если в вашей конфигурации используется БСП, мы настоятельно рекомендуем использовать программный интерфейс модуля РаботаСФайламиКлиент. Это избавит вас от необходимости писать низкоуровневый код обработки диалогов.

Рассмотрим пример использования БСП:


// На клиенте
Адрес = СформироватьФайлНаСервере();
ПараметрыФайла = РаботаСФайламиКлиент.ПараметрыСохраненияФайла();
ПараметрыФайла.ИмяФайла = "Отчет.xml";
РаботаСФайламиКлиент.СохранитьФайлНаДиске(Адрес, ПараметрыФайла);

Методы БСП хороши тем, что они уже учитывают особенности работы в веб-клиенте (браузере), где прямой доступ к файлам запрещен «песочницей», и автоматически предлагают пользователю скачать файл через стандартные средства браузера.

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

Подведем итоги нашего исследования. Для правильной организации клиент-серверного взаимодействия при создании файлов следует придерживаться следующих правил:

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

← На главную