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

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

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

Основные причины ошибок при создании XML

Рассмотрим, почему исходный код не сохраняет файл на диск пользователя:

  1. Не указано имя файла: В метод ОткрытьФайл() объекта ЗаписьXML передан путь к директории (например, E:\1\) вместо полного пути с именем файла (например, E:\1\export.xml).
  2. Разделение контекстов клиента и сервера: Код с директивой &НаСервере выполняется на стороне сервера 1С. Любые обращения к файловой системе через пути вида E:\... ищут диски сервера, а не клиентского компьютера. Кроме того, у системной службы сервера 1С (USR1CV8) может не быть прав на запись в произвольные локальные каталоги.
  3. Отображение адреса вместо выгрузки файла: Помещение двоичных данных во временное хранилище возвращает строковый адрес (вида e1cib/tempstorage/...). Простой вызов Сообщить(Адрес) на клиенте только выводит эту текстовую строку пользователю, но не производит скачивание или сохранение файла на клиентский диск.

Способ 1. Создание временного файла на сервере и скачивание на клиент

Разберем классический и надежный подход: на сервере создается файл во временном системном каталоге с помощью функции ПолучитьИмяВременногоФайла(), записываются данные, затем файл переносится во временное хранилище и удаляется с сервера. На клиенте файл принимается и сохраняется на диск пользователя.

Посмотрим на пример серверной функции:


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

Теперь рассмотрим, как корректно получить этот файл на стороне клиента в зависимости от режима работы модальности.

В синхронном режиме (при разрешенной модальности):


&НаКлиенте
Процедура СохранитьXMLСинхронно(Команда)
    АдресФайла = СформироватьXMLНаСервере();
    
    ПутьНаКлиенте = "C:\Temp\Documents.xml";
    // Получаем файл из временного хранилища и сохраняем на клиенте
    ПолучитьФайлИзВременногоХранилища(АдресФайла, ПутьНаКлиенте, Истина);
    
    Сообщить("Файл успешно сохранен: " + ПутьНаКлиенте);
КонецПроцедуры

В асинхронном режиме (режим без использования модальности):


&НаКлиенте
Процедура СохранитьXMLАсинхронно(Команда)
    АдресФайла = СформироватьXMLНаСервере();
    
    ПараметрыПолучения = Новый ПараметрыПолученияФайлов;
    ПараметрыПолучения.Интерактивно = Истина;
    
    ОписаниеФайла = Новый ОписаниеПередаваемогоФайла("Documents.xml", АдресФайла);
    
    МассивФайлов = Новый Массив;
    МассивФайлов.Добавить(ОписаниеФайла);
    
    НачатьПолучениеФайлов(Неопределено, МассивФайлов, ПараметрыПолучения, Истина);
КонецПроцедуры

Способ 2. Формирование XML в строку (без записи на диск сервера)

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

Посмотрим на реализацию:


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

Полезные рекомендации

  1. Форматирование дат: Вместо сложной ручной маски в Формат() используйте системную функцию XMLСтрока(), которая гарантирует корректный стандарт ISO 8601 для дат и чисел.
  2. Очистка временных файлов: Если создается промежуточный файл на сервере, всегда удаляйте его после считывания в ДвоичныеДанные с помощью процедуры УдалитьФайлы(), чтобы не засорять дисковое пространство сервера.
  3. Права доступа: Избегайте жестко заданных путей вроде E:\каталог\ в серверном коде — используйте ПолучитьИмяВременногоФайла().
← На главную