При работе с файлами и передачей данных между клиентом и сервером в 1С мы часто сталкиваемся с необходимостью обработки информации в модуле менеджера справочника или документа. Распространенная проблема, с которой мы сталкиваемся: данные помещаются во временное хранилище, адрес передается в функцию модуля менеджера, но при попытке получить данные метод возвращает Неопределено или возникает ошибка. Разберем подробно, почему это происходит и как гарантированно передать данные.
Чтобы понять суть проблемы, проанализируем механизм работы метода ПоместитьВоВременноеХранилище. Ключевую роль здесь играет второй параметр этого метода — адрес или уникальный идентификатор. Именно он определяет "время жизни" данных.
Рассмотрим три сценария жизненного цикла данных, которые влияют на доступность файла в модуле менеджера:
ПоместитьВоВременноеХранилище(Данные), платформа хранит данные только в течение одного серверного вызова. Как только управление возвращается с сервера на клиент, данные очищаются. Если вы попытаетесь обратиться к этому адресу в следующем вызове (например, в модуле менеджера), хранилище будет пустым.УникальныйИдентификатор открытой формы, данные живут, пока жива форма. Но модуль менеджера не имеет контекста формы, поэтому этот вариант требует аккуратной передачи идентификатора.Если ваша задача — передать файл с клиента (например, загруженный пользователем) в процедуру модуля менеджера, нам необходимо, чтобы данные "дожили" до момента выполнения кода в модуле. Рассмотрим, как это сделать правильно.
При помещении данных в хранилище нам нужно явно указать платформе, что эти данные не должны быть удалены сразу после возврата на клиент. Для этого используем конструкцию с созданием нового уникального идентификатора.
Посмотрим на пример правильного кода помещения данных:
// Создаем новый уникальный идентификатор, чтобы отвязать данные от краткосрочного контекста
АдресВХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанные, Новый УникальныйИдентификатор);
Теперь, имея этот адрес, мы можем передать его в экспортную процедуру модуля менеджера. Данные гарантированно будут доступны.
Однако, обратите внимание на важный нюанс. Так как мы привязали данные к сеансу (используя Новый УникальныйИдентификатор), платформа не очистит их автоматически до закрытия 1С пользователем. Это создает риск утечки памяти. Поэтому хорошей практикой считается удаление данных сразу после их использования.
Разберем пример кода в модуле менеджера с последующей очисткой:
Функция ВыполнитьОбработкуФайла(АдресВХранилище) Экспорт
// Получаем данные по адресу
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХранилище);
// Выполняем полезную работу с данными
Результат = РаспознатьДанные(ДвоичныеДанные);
// Важно! Освобождаем память, так как адрес был создан на базе Нового УникальногоИдентификатора
УдалитьИзВременногоХранилища(АдресВХранилище);
Возврат Результат;
КонецФункции
Проанализируем ситуацию, когда файл уже находится на сервере (например, лежит в локальной папке на диске сервера) и мы работаем в рамках серверного вызова (регламентное задание или вызов с сервера). В этом случае использование временного хранилища может быть избыточным.
Вместо того чтобы помещать файл в хранилище, получать адрес, передавать адрес и снова извлекать файл, мы можем передать объект ДвоичныеДанные напрямую как параметр функции. Это упрощает код и убирает лишние операции.
Рассмотрим пример, как это реализовать:
&НаСервере
Процедура ОбработатьЛокальныйФайл()
ПутьКФайлу = "C:\Files\Audio.wav";
// Читаем файл сразу в объект ДвоичныеДанные
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
// Передаем сами данные, а не адрес
Результат = Справочники.МойСправочник.ОтправитьНаРаспознавание(ДвоичныеДанныеФайла);
КонецПроцедуры
В модуле менеджера функция должна быть готова принять именно данные:
// Модуль менеджера
Функция ОтправитьНаРаспознавание(ВходящиеДанные) Экспорт
// ВходящиеДанные здесь - это уже тип ДвоичныеДанные, а не строка адреса
// Сразу приступаем к работе
Возврат ВнешняяКомпонента.Распознать(ВходящиеДанные);
КонецФункции
При совместной работе над задачей важно учитывать потребление ресурсов сервера. Разберем несколько рекомендаций по оптимизации:
Новый ДвоичныеДанные(Путь) загрузит весь файл в оперативную память. В таких случаях лучше передать в функцию модуля менеджера просто строку — путь к файлу (например, "C:\Temp\File.big"), и работать с ним потоково, если это позволяет логика задачи.ФоновыеЗадания.Выполнить.Таким образом, выбор решения зависит от того, где изначально находится файл (на клиенте или на сервере) и как долго нам нужно хранить эти данные. Используйте Новый УникальныйИдентификатор для надежной передачи с клиента, но не забывайте очищать память методом УдалитьИзВременногоХранилища.