Как реализовать выбор и сохранение файлов на управляемых формах в 1С?

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

Работа с файловой системой в управляемом интерфейсе «1С:Предприятия 8.3» имеет принципиальное отличие от обычных форм. Главная особенность заключается в строгом разделении контекстов: код, исполняемый на клиенте, имеет доступ к локальным дискам пользователя, в то время как серверный код «видит» только свои локальные ресурсы или сетевые папки, доступные под учетной записью службы 1С. В данной статье мы подробно разберем, как правильно организовать выбор файлов, их передачу на сервер и сохранение данных, избежав типичных ошибок новичков.

Реализация простого выбора файла на клиенте

Для начала рассмотрим самый простой сценарий: нам нужно, чтобы пользователь нажал на кнопку, выбрал файл на своем компьютере, и путь к этому файлу отобразился в реквизите формы. Для этого используется объект ДиалогВыбораФайла. Обратите внимание, что данный объект доступен только на клиенте.

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


&НаКлиенте
Процедура ВыбратьФайл(Команда)
    // Устанавливаем режим открытия файла
    Режим = РежимДиалогаВыбораФайла.Открытие;
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
    
    ДиалогОткрытияФайла.ПолноеИмяФайла = "";
    
    // Формируем фильтр для выбора только текстовых файлов
    ТекстФильтра = НСтр("ru = 'Текстовые документы'; en = 'Text documents'");
    Фильтр = ТекстФильтра + " (*.txt)|*.txt";
    ДиалогОткрытияФайла.Фильтр = Фильтр;
    
    // Разрешаем или запрещаем множественный выбор
    ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
    ДиалогОткрытияФайла.Заголовок = "Выберите файл для обработки";
    
    // Вызываем диалог. Метод .Выбрать() возвращает Истина, если пользователь нажал "Открыть"
    Если ДиалогОткрытияФайла.Выбрать() Тогда
        // Записываем путь к выбранному файлу в реквизит формы (Объект.ПутьКФайлу)
        Объект.ПутьКФайлу = ДиалогОткрытияФайла.ПолноеИмяФайла;
        
        // Если был включен множественный выбор, используем массив ДиалогОткрытияФайла.ВыбранныеФайлы
    Иначе
        Сообщить("Файл не был выбран.");
    КонецЕсли;
КонецПроцедуры

Важный момент: если вы хотите, чтобы путь к файлу записывался в реквизит обработки или документа, необходимо обращаться к нему через префикс Объект (например, Объект.ПутьКФайлу), так как в контексте управляемой формы данные хранятся в основной структуре данных формы.

Разбор ошибки «Каталог не обнаружен» при работе на сервере

Часто разработчики сталкиваются с проблемой: на локальном компьютере (в файловом режиме) код записи файла работает прекрасно, но в клиент-серверном варианте система выдает ошибку «Каталог не обнаружен». Рассмотрим, почему это происходит, на примере попытки выгрузки XML-файла.

Когда вы вызываете процедуру с директивой &НаСервере и передаете в нее путь типа "C:\MyDocuments\file.xml", сервер пытается найти этот путь на своем собственном жестком диске (на сервере приложений 1С). Естественно, такого пути там не существует, или у пользователя USR1CV8 нет прав на запись в эту папку.

Выясним причину на примере некорректного кода:


&НаСервере
Процедура ВыгрузитьНаСервере(ИмяФайлаДляСохранения)
    // ОШИБКА: Сервер не может писать напрямую на диск C: клиента!
    Запись = Новый ЗаписьXML;
    Запись.ОткрытьФайл(ИмяФайлаДляСохранения); 
    // ... логика записи ...
    Запись.Закрыть();
КонецПроцедуры

Чтобы решить эту проблему, у вас есть два пути:

  1. Выполнять всю работу на клиенте: если объем данных невелик и логика формирования файла простая, можно оставить формирование файла в процедуре &НаКлиенте. Однако это не всегда возможно, если для формирования файла нужны тяжелые запросы к базе данных.
  2. Использовать временное хранилище: сформировать файл на сервере во временную папку, передать его на клиент как ДвоичныеДанные и затем сохранить на диск пользователя.

Современный подход: Асинхронность в 1С 8.3

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

Разберем этот процесс по шагам:


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

&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
    Если ВыбранныеФайлы <> Неопределено Тогда
        Объект.ПутьКФайлу = ВыбранныеФайлы[0];
        Сообщить("Выбран файл: " + Объект.ПутьКФайлу);
    КонецЕсли;
КонецПроцедуры

Передача файла с клиента на сервер

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

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

  1. На клиенте пользователь выбирает файл.
  2. Метод ПоместитьФайл() (или асинхронный НачатьПомещениеФайла()) копирует данные файла из локальной системы во временное хранилище 1С и возвращает уникальный Адрес.
  3. Этот Адрес передается в серверную процедуру.
  4. На сервере вызывается ПолучитьИзВременногоХранилища(Адрес), что возвращает объект ДвоичныеДанные.

Пример кода для загрузки файла на сервер:


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

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

Рекомендации по работе в веб-клиенте

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

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

← На главную