Как вывести картинку на управляемую форму при открытии в 1С 8.3?

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

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

В чем заключается ошибка использования временного хранилища?

Рассмотрим ситуацию, описанную автором темы. В коде автора картинка помещается во временное хранилище, адрес вида e1cib/tempstorage/... записывается в текстовый реквизит номенклатуры, и этот адрес сохраняется в базу данных. При открытии формы автор пытается присвоить этот адрес полю картинки.

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

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

Для постоянного хранения изображений в базе данных необходимо использовать специальный тип данных — ХранилищеЗначения.

Важная архитектурная рекомендация: не добавляйте реквизиты с типом ХранилищеЗначения напрямую в часто используемые справочники (например, в справочник Номенклатура). При чтении карточки товара (например, при вызове метода ПолучитьОбъект()) система будет каждый раз считывать из СУБД тяжелые бинарные данные картинки, что существенно снизит общую производительность системы. Вместо этого создавайте подчиненный справочник (например, НоменклатураПрисоединенныеФайлы), в котором будет храниться картинка, а в основном элементе держите лишь ссылку на этот подчиненный объект.

---

Способ 1. Использование прямой навигационной ссылки (Рекомендуемый)

Самый простой, производительный и изящный способ отобразить картинку на управляемой форме — это использование механизма навигационных ссылок. Платформа «1С:Предприятие 8.3» умеет автоматически извлекать двоичные данные из базы данных и передавать их на клиент, если передать элементу формы специальный строковый адрес.

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // Проверяем, записан ли уже наш объект в базу данных
    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
        // Получаем прямую навигационную ссылку на реквизит типа ХранилищеЗначения
        // Первый параметр - ссылка на элемент БД, второй - имя реквизита, где лежит картинка
        АдресКартинки = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ХранилищеФайла");
    КонецЕсли;

КонецПроцедуры

В данном случае платформа берет на себя все заботы по кэшированию картинки, передаче ее на клиентское приложение и отображению в поле формы. Никакой ручной работы с временным хранилищем производить не требуется.

---

Способ 2. Динамическое извлечение во временное хранилище с привязкой к форме

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

Разберем по шагам, как правильно привязать время жизни картинки к жизненному циклу нашей формы, чтобы она не исчезала во время работы пользователя.

В обработчике ПриСозданииНаСервере или в любом другом серверном методе формы выполним следующий код:


&НаСервере
Процедура ЗагрузитьКартинкуНаФорму()

    // Предположим, что мы получаем двоичные данные из реквизита ХранилищеЗначения
    ДвоичныеДанныеКартинки = Объект.ХранилищеФайла.Получить();
    
    Если ДвоичныеДанныеКартинки <> Неопределено Тогда
        // КРИТИЧЕСКИ ВАЖНО: передаем УникальныйИдентификатор формы вторым параметром.
        // Это указывает платформе, что картинка должна жить во временном хранилище
        // ровно до тех пор, пока данная форма открыта у пользователя.
        АдресКартинки = ПоместитьВоВременноеХранилище(ДвоичныеДанныеКартинки, ЭтаФорма.УникальныйИдентификатор);
    КонецЕсли;

КонецПроцедуры

Благодаря использованию свойства ЭтаФорма.УникальныйИдентификатор платформа гарантирует, что адрес в переменной АдресКартинки будет оставаться рабочим и доступным для отображения на клиенте при любых серверных вызовах в контексте этой формы.

---

Как реализовать интерактивную загрузку новой картинки пользователем?

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

Шаг 1. На клиенте описываем процедуру выбора файла и его асинхронной отправки на сервер:


&НаКлиенте
Процедура ВыбратьФайлКартинки(Команда)

    // Настройки диалога выбора файла
    ПараметрыВыбора = Новый ПараметрыПомещенияФайла;
    ПараметрыВыбора.Интерактивно = Истина;
    ПараметрыВыбора.Фильтр = "Изображения (*.png;*.jpg)|*.png;*.jpg";
    
    // Асинхронно отправляем файл на сервер во временное хранилище
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
    НачатьПомещениеФайлаНаСервер(ОписаниеОповещения,,, ПараметрыВыбора, ЭтаФорма.УникальныйИдентификатор);

КонецПроцедуры

&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, ДополнительныеПараметры) Экспорт

    Если Результат <> Неопределено И Результат.ПомещениеФайлаЗавершено Тогда
        // Присваиваем полученный временный адрес реквизиту формы.
        // Пользователь мгновенно увидит новую картинку на форме!
        АдресКартинки = Результат.Адрес;
        
        // Устанавливаем признак модифицированности формы, чтобы платформа предложила сохранить изменения
        Модифицированность = Истина;
    КонецЕсли;

КонецПроцедуры

Шаг 2. На сервере в модуле формы перехватываем запись объекта и сохраняем файл в базу данных:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)

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

КонецПроцедуры

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

← На главную