Как получить файл из временного хранилища по уникальному идентификатору и почему адрес нельзя хранить в базе данных

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

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

Разбор механизма помещения данных во временное хранилище

Для начала проанализируем синтаксис основной функции, с которой начинается работа. Когда мы вызываем метод ПоместитьВоВременноеХранилище, мы передаем данные и (опционально) адрес или идентификатор владельца. Рассмотрим типичный пример кода:


// Пример помещения двоичных данных во временное хранилище
ДанныеФайла = Новый ДвоичныеДанные("C:\temp\report.pdf");
АдресХранилища = ПоместитьВоВременноеХранилище(ДанныеФайла, Новый УникальныйИдентификатор());

Здесь кроется первое заблуждение. Параметр Адрес (второй аргумент функции) может принимать УникальныйИдентификатор. Многие полагают, что если передать туда свой GUID, то по нему же можно будет потом и забрать файл. Однако это не так. Рассмотрим, что происходит на самом деле:

  1. Если во второй параметр передан УникальныйИдентификатор, система воспринимает его как идентификатор формы или владельца. Это определяет время жизни данных.
  2. Функция всегда возвращает строку — уникальный внутренний адрес вида e1cib/tempstorage/....
  3. Для получения данных методом ПолучитьИзВременногоХранилища необходимо использовать именно эту возвращенную строку, а не тот GUID, который вы передали в качестве владельца.

Структура и длина адреса временного хранилища

Разберем, почему адрес временного хранилища такой длинный (обычно около 100 символов и более). Посмотрим на типичный формат адреса:

e1cib/tempstorage/157261cf-3edc-4966-8213-1013f716267f?seanceId=72885707-f4be-487f-a4ee-4a8d6cc15e37

Проанализируем составляющие этой строки:

Важно понимать: параметр seanceId привязывает данные к конкретному сеансу. Это сделано для безопасности, чтобы один пользователь не мог получить доступ к временным файлам другого, просто угадав GUID. Именно из-за этой служебной информации адрес не помещается в стандартные поля ограниченной длины (например, в строковый ресурс регистра сведений длиной 50 символов).

Жизненный цикл данных (Lifecycle)

Выясним причину, по которой данные из временного хранилища внезапно "исчезают". Время жизни объекта в tempstorage жестко ограничено. Рассмотрим три сценария:

  1. Привязка к форме: Если при помещении данных передан УникальныйИдентификатор формы, данные будут удалены автоматически, как только пользователь закроет эту форму.
  2. Привязка к сеансу: Если адрес не привязан к конкретной форме, данные живут до завершения сеанса пользователя или до перезагрузки сервера 1С.
  3. Ручное управление: Начиная с версии платформы 8.3.15, мы можем использовать метод УдалитьИзВременногоХранилища(Адрес). Это крайне полезно для оптимизации потребления оперативной памяти при работе с тяжелыми файлами.

Типичная ошибка: Хранение адреса в регистре сведений

Проанализируем ситуацию, когда разработчик пытается записать адрес временного хранилища в базу данных (например, в ресурс регистра сведений). Это является грубой архитектурной ошибкой по нескольким причинам:

Во-первых, как мы уже выяснили, адрес динамический и содержит seanceId. После того как пользователь выйдет из системы и зайдет снова, идентификатор сеанса изменится, и старая ссылка в регистре станет бесполезной — по ней ничего нельзя будет получить.

Во-вторых, временное хранилище физически может находиться в оперативной памяти сервера. При любом регламентном перезапуске службы rphost или очистке временных папок сервера данные будут безвозвратно утеряны. Ссылка в регистре останется "битой".

В-третьих, ограничение длины строки (например, 50 символов) не позволяет хранить полный адрес. Попытка "обрезать" адрес или хранить только GUID данных лишает нас возможности программно восстановить работоспособную ссылку, так как мы не знаем seanceId.

Как правильно организовать постоянное хранение файлов

Если ваша задача — сохранить файл так, чтобы он был доступен и завтра, и послезавтра, и другим пользователям, забудьте про временное хранилище для этих целей. Рассмотрим правильный алгоритм действий:

  1. Создайте в конфигурации справочник (например, ПрисоединенныеФайлы) или используйте существующий в БСП.
  2. Добавьте реквизит с типом ХранилищеЗначения.
  3. При загрузке файла получите данные из временного хранилища и поместите их в этот реквизит.

Пример кода для сохранения данных из временного хранилища в базу:


// Предположим, АдресВХ пришел с клиента
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХ);

ОбъектФайл = Справочники.Файлы.СоздатьЭлемент();
ОбъектФайл.Наименование = "МойДокумент.pdf";
// Помещаем данные в ХранилищеЗначения
ОбъектФайл.ДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
ОбъектФайл.Записать();

Как обойти ограничение, если данные действительно временные

Если же данные вам нужны только в рамках текущего сеанса, но вам неудобно передавать длинную строку адреса между процедурами, можно использовать временное соответствие в оперативной памяти (например, в параметрах сеанса или в глобальной переменной модуля).

Рассмотрим по шагам этот прием:

Важное примечание: Этот метод все равно не сделает данные постоянными. Он лишь поможет "спрятать" длинную ссылку внутри сеанса.

Особенности работы в фоновых заданиях

Посмотрим на ситуацию с фоновыми заданиями. Если вы поместили файл в хранилище в контексте формы и передали адрес в фоновое задание, оно может не увидеть эти данные. Почему? Потому что фоновое задание выполняется в собственном сеансе. Для корректной передачи данных в фоновое задание следует помещать их во временное хранилище без привязки к форме, используя в качестве идентификатора владельца новый УникальныйИдентификатор, не связанный с интерфейсом.

Подведем итог: использование временного хранилища — это мощный инструмент для оперативной работы с данными, но он требует четкого понимания границ применимости. Никогда не сохраняйте адреса вида e1cib/tempstorage/ в реквизиты базы данных, если планируете обращаться к этим данным за пределами текущего пользовательского сеанса.

← На главную