При разработке на управляемых формах в платформе 1С:Предприятие 8.3 разработчики часто сталкиваются с разделением контекстов выполнения кода: &НаКлиенте и &НаСервере. Классическая задача — предоставить пользователю интерактивный выбор файла на его компьютере через диалог и затем обработать данные этого файла (например, загрузить таблицу DBF) в серверной процедуре.
Разберем типичные ошибки при передаче данных между контекстами, выясним причину изоляции переменных модуля и рассмотрим правильные варианты реализации передачи пути и самого файла на сервер.
Посмотрим на частую ошибку начинающих разработчиков: объявление переменной в начале модуля формы через ключевое слово Перем ИмяФайла; в надежде, что значение, присвоенное на клиенте, будет доступно на сервере.
Проанализируем причину, почему этот подход не работает:
Перем, создаются отдельно для экземпляра формы на клиенте и отдельно для вызова на сервере.ДиалогВыбораФайла доступен исключительно в контексте &НаКлиенте, тогда как тяжелая обработка данных и чтение справочников обычно выполняются в блоке &НаСервере.Если база данных работает в файловом режиме или клиент и сервер физически расположены на одном компьютере (а также если файл расположен в общедоступном сетевом ресурсе с одинаковым UNC-путем), путь к файлу можно передать строкой в качестве параметра серверной процедуры.
Разберем по шагам правильную реализацию вызова:
ДиалогВыбораФайла и получаем свойство ПолноеИмяФайла.ОткрытьФайл объекта XBase.Посмотрим на рабочий пример кода:
&НаКлиенте
Процедура СинхронизироватьТФ(Команда)
ДВФ = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДВФ.Заголовок = "Выберите файл для обработки";
ДВФ.ПредварительныйПросмотр = Ложь;
ДВФ.Фильтр = "Файлы DBF (*.dbf)|*.dbf";
Если ДВФ.Выбрать() Тогда
ИмяВыбранногоФайла = ДВФ.ПолноеИмяФайла;
СинхронизироватьТФНаСервере(ИмяВыбранногоФайла);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура СинхронизироватьТФНаСервере(ПутьКФайлу)
// Выполняем предварительные действия с данными
Менеджер = Справочники.ФИО;
Выборка = Менеджер.Выбрать();
Пока Выборка.Следующий() Цикл
СТ = Выборка.ПолучитьОбъект();
СТ.Статус = "Нет";
СТ.Записать();
КонецЦикла;
// Работа с файлом DBF
ФайлDBF = Новый XBase;
ФайлDBF.Кодировка = КодировкаXBase.OEM;
// Проверяем, не открыт ли файл ранее
Если ФайлDBF.Открыта() Тогда
ФайлDBF.ЗакрытьФайл();
КонецЕсли;
ФайлDBF.ОткрытьФайл(ПутьКФайлу, , Истина);
// Чтение данных...
Пока НЕ ФайлDBF.ВКонце() Цикл
// Обработка строк DBF
ФайлDBF.Следующий();
КонецЦикла;
ФайлDBF.ЗакрытьФайл();
КонецПроцедуры
При выполнении чтения DBF-файлов часто возникает исключение: «Перед выполнением операции нужно закрыть базу».
Выясним причину этой ошибки: метод ОткрытьФайл() вызывается у экземпляра объекта XBase, который уже содержит открытую таблицу базы данных. Чтобы избежать этой ошибки:
Новый XBase перед открытием файла.ФайлDBF.Открыта() и вызывайте метод ФайлDBF.ЗакрытьФайл() перед повторным открытием.КодировкаXBase.OEM, а для файлов Windows — КодировкаXBase.ANSI.Рассмотрим ограничение первого способа: в клиент-серверном варианте (SQL) служба сервера 1С:Предприятия работает на отдельном физическом сервере и не имеет доступа к локальному диску C:\ клиентского компьютера пользователя. В этом случае передача строкового пути вызовет ошибку отсутствия файла на сервере.
Для создания универсального решения, которое работает в любом режиме (включая веб-клиент и клиент-сервер), разберем передачу содержимого файла через Временное хранилище:
ПолучитьИмяВременногоФайла().Посмотрим на пример универсального кода:
&НаКлиенте
Процедура ЗагрузитьФайлУниверсально(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Файлы DBF (*.dbf)|*.dbf";
Если Диалог.Выбрать() Тогда
АдресВХ = "";
ПоместитьФайл(АдресВХ, Диалог.ПолноеИмяФайла, , Ложь, УникальныйИдентификатор);
ОбработатьФайлНаСервере(АдресВХ);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ОбработатьФайлНаСервере(АдресВХ)
// Получаем двоичные данные из временного хранилища
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХ);
// Создаем временный файл на диске сервера
ВременныйПуть = ПолучитьИмяВременногоФайла("dbf");
ДвоичныеДанные.Записать(ВременныйПуть);
ФайлDBF = Новый XBase;
ФайлDBF.Кодировка = КодировкаXBase.OEM;
Попытка
ФайлDBF.ОткрытьФайл(ВременныйПуть, , Истина);
Пока НЕ ФайлDBF.ВКонце() Цикл
// Чтение полей DBF
ФайлDBF.Следующий();
КонецЦикла;
ФайлDBF.ЗакрытьФайл();
Исключение
Если ФайлDBF.Открыта() Тогда
ФайлDBF.ЗакрытьФайл();
КонецЕсли;
УдалитьФайлы(ВременныйПуть);
ВызватьИсключение;
КонецПопытки;
// Очищаем временные данные
УдалитьФайлы(ВременныйПуть);
УдалитьИзВременногоХранилища(АдресВХ);
КонецПроцедуры
Использование параметров процедур и механизмов временного хранилища обеспечивает правильную передачу данных между клиентом и сервером в полном соответствии с архитектурой управляемого приложения 1С:Предприятия.