Работа с файловой системой в управляемом интерфейсе «1С:Предприятия 8.3» имеет принципиальное отличие от обычных форм. Главная особенность заключается в строгом разделении контекстов: код, исполняемый на клиенте, имеет доступ к локальным дискам пользователя, в то время как серверный код «видит» только свои локальные ресурсы или сетевые папки, доступные под учетной записью службы 1С. В данной статье мы подробно разберем, как правильно организовать выбор файлов, их передачу на сервер и сохранение данных, избежав типичных ошибок новичков.
Для начала рассмотрим самый простой сценарий: нам нужно, чтобы пользователь нажал на кнопку, выбрал файл на своем компьютере, и путь к этому файлу отобразился в реквизите формы. Для этого используется объект ДиалогВыбораФайла. Обратите внимание, что данный объект доступен только на клиенте.
Проанализируем типовой пример кода, который позволяет выбрать один или несколько файлов:
&НаКлиенте
Процедура ВыбратьФайл(Команда)
// Устанавливаем режим открытия файла
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
// Формируем фильтр для выбора только текстовых файлов
ТекстФильтра = НСтр("ru = 'Текстовые документы'; en = 'Text documents'");
Фильтр = ТекстФильтра + " (*.txt)|*.txt";
ДиалогОткрытияФайла.Фильтр = Фильтр;
// Разрешаем или запрещаем множественный выбор
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл для обработки";
// Вызываем диалог. Метод .Выбрать() возвращает Истина, если пользователь нажал "Открыть"
Если ДиалогОткрытияФайла.Выбрать() Тогда
// Записываем путь к выбранному файлу в реквизит формы (Объект.ПутьКФайлу)
Объект.ПутьКФайлу = ДиалогОткрытияФайла.ПолноеИмяФайла;
// Если был включен множественный выбор, используем массив ДиалогОткрытияФайла.ВыбранныеФайлы
Иначе
Сообщить("Файл не был выбран.");
КонецЕсли;
КонецПроцедуры
Важный момент: если вы хотите, чтобы путь к файлу записывался в реквизит обработки или документа, необходимо обращаться к нему через префикс Объект (например, Объект.ПутьКФайлу), так как в контексте управляемой формы данные хранятся в основной структуре данных формы.
Часто разработчики сталкиваются с проблемой: на локальном компьютере (в файловом режиме) код записи файла работает прекрасно, но в клиент-серверном варианте система выдает ошибку «Каталог не обнаружен». Рассмотрим, почему это происходит, на примере попытки выгрузки XML-файла.
Когда вы вызываете процедуру с директивой &НаСервере и передаете в нее путь типа "C:\MyDocuments\file.xml", сервер пытается найти этот путь на своем собственном жестком диске (на сервере приложений 1С). Естественно, такого пути там не существует, или у пользователя USR1CV8 нет прав на запись в эту папку.
Выясним причину на примере некорректного кода:
&НаСервере
Процедура ВыгрузитьНаСервере(ИмяФайлаДляСохранения)
// ОШИБКА: Сервер не может писать напрямую на диск C: клиента!
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ИмяФайлаДляСохранения);
// ... логика записи ...
Запись.Закрыть();
КонецПроцедуры
Чтобы решить эту проблему, у вас есть два пути:
&НаКлиенте. Однако это не всегда возможно, если для формирования файла нужны тяжелые запросы к базе данных.ДвоичныеДанные и затем сохранить на диск пользователя.Начиная с последних версий платформы 8.3, использование синхронных методов (таких как Выбрать()) в веб-клиенте ограничено. Программа может выдать предупреждение или вовсе не сработать. Рассмотрим, как выглядит современный асинхронный выбор файла с использованием ОписаниеОповещения.
Разберем этот процесс по шагам:
&НаКлиенте
Процедура НачатьВыборФайла(Команда)
// Создаем описание оповещения, которое укажет, какую процедуру вызвать после закрытия диалога
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл";
// Вместо Выбрать() используем Показать()
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено Тогда
Объект.ПутьКФайлу = ВыбранныеФайлы[0];
Сообщить("Выбран файл: " + Объект.ПутьКФайлу);
КонецЕсли;
КонецПроцедуры
Если ваша задача — не просто выбрать имя файла, а прочитать его содержимое на сервере (например, загрузить данные из Excel или XML в базу), необходимо передать сам файл в облако сервера. Для этого используется механизм временного хранилища.
Проанализируем алгоритм:
ПоместитьФайл() (или асинхронный НачатьПомещениеФайла()) копирует данные файла из локальной системы во временное хранилище 1С и возвращает уникальный Адрес.Адрес передается в серверную процедуру.ПолучитьИзВременногоХранилища(Адрес), что возвращает объект ДвоичныеДанные.Пример кода для загрузки файла на сервер:
&НаКлиенте
Процедура ЗагрузитьФайлНаСервер(Команда)
АдресХранилища = "";
ВыбранноеИмя = "";
// Помещаем файл во временное хранилище
Если ПоместитьФайл(АдресХранилища, "", ВыбранноеИмя, Истина) Тогда
// Теперь вызываем серверную процедуру, передавая адрес
ОбработатьФайлНаСервере(АдресХранилища);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ОбработатьФайлНаСервере(Адрес)
// Получаем данные из хранилища
ДанныеФайла = ПолучитьИзВременногоХранилища(Адрес);
// Можем сохранить во временный файл на диске сервера, если нужно
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
ДанныеФайла.Записать(ИмяВременногоФайла);
// Читаем данные...
// ЧтениеXML = Новый ЧтениеXML;
// ЧтениеXML.ОткрытьФайл(ИмяВременногоФайла);
// Не забываем удалять временные файлы на сервере!
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
При работе через браузер возможности 1С ограничены политиками безопасности. Для полноценной работы с файлами (особенно для программного сканирования папок) пользователю может потребоваться установить расширение для работы с файлами. Вы можете программно проверить наличие расширения и предложить его установку с помощью метода НачатьПодключениеРасширенияРаботыСФайлами().
Подведем итог: для успешной работы с файлами в управляемых формах всегда четко разделяйте, где происходит взаимодействие с пользователем (клиент), а где — обработка данных (сервер). Никогда не передавайте «пути» к файлам на сервер с расчетом, что он их прочитает напрямую. Всегда используйте ДвоичныеДанные и Временное хранилище для обмена информацией между локальным ПК и базой данных.