При программном формировании XML-файлов в клиент-серверной архитектуре и управляемых формах разработчики часто сталкиваются с ситуацией, когда код выполняется без явных синтаксических ошибок, но файл на локальном компьютере не появляется. Проанализируем типичные причины этой проблемы и разберем по шагам корректные способы выгрузки XML.
Рассмотрим, почему исходный код не сохраняет файл на диск пользователя:
ОткрытьФайл() объекта ЗаписьXML передан путь к директории (например, E:\1\) вместо полного пути с именем файла (например, E:\1\export.xml).&НаСервере выполняется на стороне сервера 1С. Любые обращения к файловой системе через пути вида E:\... ищут диски сервера, а не клиентского компьютера. Кроме того, у системной службы сервера 1С (USR1CV8) может не быть прав на запись в произвольные локальные каталоги.e1cib/tempstorage/...). Простой вызов Сообщить(Адрес) на клиенте только выводит эту текстовую строку пользователю, но не производит скачивание или сохранение файла на клиентский диск.Разберем классический и надежный подход: на сервере создается файл во временном системном каталоге с помощью функции ПолучитьИмяВременногоФайла(), записываются данные, затем файл переносится во временное хранилище и удаляется с сервера. На клиенте файл принимается и сохраняется на диск пользователя.
Посмотрим на пример серверной функции:
&НаСервере
Функция Сформировать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", АдресФайла);
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ОписаниеФайла);
НачатьПолучениеФайлов(Неопределено, МассивФайлов, ПараметрыПолучения, Истина);
КонецПроцедуры
Если объем выгружаемых данных невелик, можно полностью исключить обращение к файловой системе сервера. Для этого используем метод УстановитьСтроку() объекта ЗаписьXML.
Посмотрим на реализацию:
&НаСервере
Функция СформироватьСтрокуXML()
ПараметрыЗаписи = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина, Символы.Таб);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(ПараметрыЗаписи);
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Корень");
ЗаписьXML.ЗаписатьНачалоЭлемента("Элемент");
ЗаписьXML.ЗаписатьТекст("Пример данных");
ЗаписьXML.ЗаписатьКонецЭлемента();
ЗаписьXML.ЗаписатьКонецЭлемента();
// Закрытие возвращает сформированный текст XML
СтрокаXML = ЗаписьXML.Закрыть();
// Получаем двоичные данные напрямую из строки без промежуточных файлов
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(СтрокаXML, "UTF-8");
Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанные, Новый УникальныйИдентификатор);
КонецФункции
Формат() используйте системную функцию XMLСтрока(), которая гарантирует корректный стандарт ISO 8601 для дат и чисел.ДвоичныеДанные с помощью процедуры УдалитьФайлы(), чтобы не засорять дисковое пространство сервера.E:\каталог\ в серверном коде — используйте ПолучитьИмяВременногоФайла().