Как сохранить сформированный текст XML в файл на диск в управляемом приложении 1С

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

В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача: программно сформировать XML-документ и предоставить пользователю возможность сохранить его на локальный диск. В управляемых формах, особенно в современных конфигурациях (таких как БП 3.0, ЗУП 3.1 или ERP), задача осложняется тем, что использование модальных окон запрещено, а работа с файловой системой на стороне клиента имеет свои особенности. Рассмотрим подробнее, как реализовать этот функционал правильно и эффективно.

Метод 1: Использование объекта ДиалогВыбораФайла в немодальном режиме

Самый распространенный способ — это использование стандартного объекта ДиалогВыбораФайла. Поскольку в управляемом приложении мы не можем использовать метод Выбрать(), который блокирует работу интерфейса, мы воспользуемся методом Показать(). Разберем по шагам, как это работает.

Сначала нам нужно создать описание оповещения — специальный объект, который укажет системе, какую процедуру выполнить после того, как пользователь выберет путь к файлу или нажмет «Отмена».


&НаКлиенте
Процедура ФормированиеXML(Команда)
    
    // Получаем строку XML (предположим, она формируется на сервере)
    СтрокаXML = СформироватьXMLФайлНаСервере();    
    
    // Создаем диалог
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
    Диалог.Заголовок = "Выберите путь для сохранения файла XML";
    Диалог.ПолноеИмяФайла = "Данные.xml";
    Диалог.Фильтр = "Файлы XML (*.xml)|*.xml";
    
    // Описываем процедуру, которая выполнится после закрытия диалога
    Оповещение = Новый ОписаниеОповещения("ЗавершитьСохранениеФайла", ЭтотОбъект, СтрокаXML);
    
    // Открываем диалог
    Диалог.Показать(Оповещение);
    
КонецПроцедуры

&НаКлиенте
Процедура ЗавершитьСохранениеФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныеФайлы = Неопределено Тогда
        Возврат; // Пользователь отказался от выбора
    КонецЕсли;
    
    ПутьКФайлу = ВыбранныеФайлы[0];
    СтрокаXML = ДополнительныеПараметры;
    
    // Записываем текст в файл
    Текст = Новый ТекстовыйДокумент;
    Текст.УстановитьТекст(СтрокаXML);
    Попытка
        Текст.Записать(ПутьКФайлу, КодировкаТекста.UTF8);
        Сообщить("Файл успешно сохранен: " + ПутьКФайлу);
    Исключение
        Предупреждение("Ошибка при записи файла: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

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

Метод 2: Работа через двоичные данные и временное хранилище

Использование ТекстовыйДокумент иногда может приводить к проблемам с кодировкой (например, автоматическое добавление BOM-метки в UTF-8), что критично для некоторых государственных сервисов. Более надежный способ — преобразовать строку в ДвоичныеДанные. Выясним причину: объект ДвоичныеДанные сохраняет информацию байт-в-байт.

Рассмотрим пример, где файл сначала формируется во временном хранилище на сервере, а затем скачивается клиентом. Это "золотой стандарт" для веб-клиентов и тонких клиентов.


&НаКлиенте
Процедура СохранитьXMLЧерезХранилище(Команда)
    
    // Формируем данные на сервере и получаем адрес во временном хранилище
    Результат = СформироватьФайлИПоместитьВХранилище();
    
    ПараметрыПолучения = Новый ПараметрыПолученияФайла;
    ПараметрыПолучения.Заголовок = "Сохранение XML";
    
    // Метод ПолучитьФайл инициирует стандартную загрузку файла в браузере 
    // или открывает диалог сохранения в тонком клиенте
    ПолучитьФайл(Результат.Адрес, Результат.ИмяФайла, Истина);
    
КонецПроцедуры

&НаСервере
Функция СформироватьФайлИПоместитьВХранилище()
    
    СтрокаXML = "<?xml version=""1.0"" encoding=""UTF-8""?><root>Данные</root>";
    
    // Преобразуем строку в двоичные данные с явным указанием кодировки
    ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(СтрокаXML, КодировкаТекста.UTF8, Ложь);
    
    ИмяФайла = "export.xml";
    Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, Новый УникальныйИдентификатор);
    
    Возврат Новый Структура("Адрес, ИмяФайла", Адрес, ИмяФайла);
    
КонецФункции

Метод 3: Использование функций БСП (Библиотека стандартных подсистем)

Если вы работаете в современной конфигурации, такой как "1С:Бухгалтерия 3.0", крайне рекомендуем использовать программный интерфейс БСП. Это избавит вас от необходимости вручную прописывать ОписаниеОповещения. Общий модуль ФайловаяСистемаКлиент содержит готовый метод СохранитьФайл().

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


&НаКлиенте
Процедура СохранитьЧерезБСП(Команда)
    
    АдресХранилища = ПодготовитьФайлНаСервере();
    
    ПараметрыСохранения = ФайловаяСистемаКлиент.ПараметрыСохраненияФайла();
    ПараметрыСохранения.ИмяФайла = "Отчет.xml";
    ПараметрыСохранения.Заголовок = "Куда сохранить XML?";
    
    ФайловаяСистемаКлиент.СохранитьФайл(Неопределено, АдресХранилища, ПараметрыСохранения);
    
КонецПроцедуры

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

Метод 4: Использование объекта ЗаписьXML напрямую

Разберем ситуацию, когда данных очень много. Вместо того чтобы формировать гигантскую строку в памяти, лучше использовать объект ЗаписьXML. Он позволяет записывать данные порциями (потоково), что значительно экономит оперативную память сервера.


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

Важный момент: Обратите внимание на третий параметр в ПараметрыЗаписиXML. Установка его в значение Ложь гарантирует, что в начале файла не будет лишних невидимых символов (Byte Order Mark), которые часто мешают корректному чтению XML сторонними программами.

Метод 5: Современные асинхронные вызовы (платформа 8.3.15+)

В последних версиях платформы 1С реализован механизм Ждать (Async/Await), который делает код линейным, несмотря на использование диалогов. Если ваша конфигурация работает на режиме совместимости 8.3.15 и выше, можно использовать ПолучитьФайлыАсинхр.

Проанализируем пример:


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

Использование асинхронных методов — это наиболее современный подход, который избавляет от необходимости плодить множество процедур-оповещений ("ЗавершитьСохранение", "ПослеВыбора" и т.д.) и делает код значительно более читаемым.

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

Для выбора оптимального способа сохранения XML на диск воспользуйтесь следующими правилами:

  1. Если есть БСП: Всегда используйте ФайловаяСистемаКлиент.СохранитьФайл(). Это самый надежный способ, протестированный вендором.
  2. Для простых строк: Если XML небольшой, можно сформировать его в строку на сервере, вернуть на клиент и сохранить через ТекстовыйДокумент с использованием ОписаниеОповещения.
  3. Для сложных структур: Используйте ЗаписьXML на сервере, помещайте результат в ДвоичныеДанные и передавайте на клиент через временное хранилище. Это гарантирует правильную кодировку.
  4. Контроль кодировки: Помните, что для XML крайне важна кодировка UTF-8. Всегда явно указывайте параметры записи, чтобы избежать проблем с BOM.

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

← На главную