При разработке на платформе 1С:Предприятие 8.3, особенно в режиме управляемых форм, программисты часто сталкиваются с ситуацией, когда код, написанный по привычным «синхронным» канонам, отказывается работать. Типичный пример — использование метода НачатьПомещениеФайловНаСервер. Попытка обратиться к результату выполнения этого метода сразу в следующей строке кода неизбежно приводит к ошибке: «Переменная не определена (ПомещенныеФайлы)». В этой статье мы подробно разберем, почему так происходит, и научимся правильно организовывать процесс загрузки файлов.
Проанализируем ситуацию, представленную в вопросе. Автор пытается вызвать метод НачатьПомещениеФайловНаСервер и сразу после него запустить цикл Для каждого по переменной, которая, по его мнению, должна содержать результат загрузки. Однако платформа выдает ошибку. Выясним причину: методы, название которых начинается с префикса «Начать...», являются асинхронными.
Что это означает на практике? Когда система выполняет строку с асинхронным методом, она лишь инициирует процесс (в данном случае — передачу файла на сервер) и, не дожидаясь его завершения, мгновенно переходит к выполнению следующей строки кода. В этот момент файл еще может физически передаваться по сети, и никакого массива ПомещенныеФайлы в текущем контексте выполнения просто не существует. Переменная, содержащая результат, не возвращается методом напрямую — она передается «снаружи» в специальную процедуру завершения.
Для работы с асинхронными методами в 1С используется механизм оповещений. Чтобы программа узнала, что загрузка завершена, и получила доступ к данным, мы должны заранее подготовить объект типа ОписаниеОповещенияОЗавершении. Этот объект «говорит» системе: «Когда закончишь загрузку файлов, вызови, пожалуйста, вот эту конкретную процедуру и передай в нее результат».
Рассмотрим структуру правильного подхода. Процесс разделяется на два этапа:
Перепишем исходный код, чтобы он соответствовал стандартам современной разработки на платформе 1С. Вместо попытки перебрать несуществующий массив в основной процедуре, мы создадим правильную структуру вызова.
Шаг 1. Инициируем загрузку
В этой части кода мы создаем оповещение, указывая имя процедуры, которая обработает результат, и модуль, где эта процедура расположена (обычно это ЭтотОбъект для формы).
&НаКлиенте
Процедура ЗагрузитьФайлНаСервер()
// 1. Создаем описание оповещения
// Параметры: "ИмяПроцедурыЗавершения", МодульГдеОнаНаходится
Оповещение = Новый ОписаниеОповещенияОЗавершении("ЗагрузитьФайлЗавершение", ЭтотОбъект);
// 2. Вызываем асинхронный метод
// Мы передаем путь к локальному файлу и идентификатор формы для привязки к хранилищу
НачатьПомещениеФайловНаСервер(Оповещение, , , "D:\test244.pdf", ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры
Шаг 2. Описываем процедуру завершения
Эта процедура должна иметь строго определенный набор параметров. Именно сюда платформа передаст массив Результат, который и будет содержать информацию о помещенных файлах.
&НаКлиенте
Процедура ЗагрузитьФайлЗавершение(Результат, ДополнительныеПараметры) Экспорт
// Проверяем, не была ли отменена операция или не возникла ли ошибка
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
// Теперь мы можем безопасно перебрать массив результатов
Для Каждого ПереданныйФайл Из Результат Цикл
// Адрес во временном хранилище — это то, что нам нужно для работы на сервере
АдресХранилища = ПереданныйФайл.Адрес;
ИмяФайла = ПереданныйФайл.СсылкаНаФайл.Имя;
// Здесь мы можем вызвать серверную процедуру для сохранения данных в базу
СохранитьДанныеВОбъектНаСервере(АдресХранилища, ИмяФайла);
КонецЦикла;
КонецПроцедуры
Внутри цикла мы работаем с объектами типа ОписаниеПомещенногоФайла. Посмотрим на его ключевые свойства, которые помогут нам в дальнейшей обработке:
Адрес: это строка, представляющая собой путь к данным во временном хранилище (вида e1cib/tempstorage/...). Этот адрес необходимо передать на серверную сторону, чтобы с помощью метода ПолучитьИзВременногоХранилища(Адрес) извлечь двоичные данные файла.СсылкаНаФайл: объект, содержащий метаданные исходного файла на диске пользователя (имя, путь, расширение). Это полезно, если нам нужно сохранить оригинальное название документа в реквизитах базы данных.В платформе существует и синхронный аналог — ПоместитьФайлыНаСервер. Почему же мы используем более сложный асинхронный вариант? Разберем отличия:
Синхронный метод (без «Начать»): полностью блокирует интерфейс программы до тех пор, пока файл не будет передан. Если файл весит 100 МБ, а интернет медленный, пользователь будет видеть «зависшее» окно в течение нескольких минут. Более того, в веб-клиенте использование синхронных методов часто ограничено или вовсе запрещено политиками браузеров.
Асинхронный метод (Начать...): работает в фоновом режиме. Интерфейс остается отзывчивым, пользователь может продолжать работу в форме, пока файл «летит» на сервер. Именно этот метод является рекомендуемым и обязательным для использования в современных конфигурациях на управляемых формах.
Обратите внимание на параметр УникальныйИдентификатор, который мы передали в метод. Это критически важный момент для управления памятью:
УникальныйИдентификатор формы, то файл во временном хранилище будет жить ровно столько, сколько открыта эта форма. Как только пользователь закроет форму, временный файл будет удален автоматически.ХранилищеЗначения) или сохранить на диск сервера.Если ваш код работает в тонком клиенте, но выдает ошибки в браузере, проанализируйте способ указания пути к файлу. В коде автора указан жесткий путь: "D:\test244.pdf". По соображениям безопасности современные браузеры запрещают веб-страницам (и веб-клиенту 1С) обращаться к локальным дискам пользователя без его явного согласия.
Для стабильной работы рекомендуется использовать второй параметр метода — ДиалогВыбораФайла или предварительно вызывать интерактивный выбор файла. Если же требуется автоматическая загрузка по заданному пути, убедитесь, что в браузере установлено расширение для работы с файлами 1С, и пользователь дал соответствующие разрешения в настройках операционной системы.
Мы выяснили, что ошибка «Переменная не определена» — это прямое следствие игнорирования асинхронной природы методов загрузки. Для исправления ситуации необходимо:
ОписаниеОповещенияОЗавершении.ПомещенныеФайлы в отдельную процедуру-callback.Такой подход не только исправляет ошибку, но и делает ваше приложение более стабильным и дружелюбным к пользователю, обеспечивая плавную работу интерфейса даже при передаче больших объемов данных.