В процессе разработки часто возникает задача получения изображений из внешних источников (поможет обработка загрузки и оптимизации внешних изображений), например, через HTTP-соединение, при программной конвертации отчетов в графику или из внешних файлов. Часто эти данные приходят к нам в виде объекта ДвоичныеДанные. Однако простого наличия этих данных недостаточно для того, чтобы пользователь увидел изображение на экране. Разберем пошагово, как правильно преобразовать эти данные и связать их с интерфейсом управляемой формы.
Рассмотрим типичную ситуацию: у нас есть справочник с реквизитом Изображение (тип ХранилищеЗначения). На форме создано строковое поле, связанное с элементом вида Поле картинки. Проблема заключается в том, что запись объекта в базу данных не вызывает автоматического обновления картинки на форме, а попытки прямого присвоения объекта Картинка строковому реквизиту не приводят к успеху.
Для того чтобы платформа могла отрисовать изображение в управляемом приложении, ей нужен адрес этого изображения. Самый быстрый способ получить такой адрес для данных, которые еще не зафиксированы в базе или только что получены по сети — использовать Временное хранилище. Проанализируем правильный алгоритм действий на сервере:
&НаСервере
Процедура СоздатьКартинкуНаСервере(Двоичные)
// 1. Помещаем двоичные данные во временное хранилище.
// Обязательно передаем УникальныйИдентификатор формы,
// чтобы данные жили столько же, сколько открыта форма.
АдресКартинки = ПоместитьВоВременноеХранилище(Двоичные, УникальныйИдентификатор);
// 2. Если нужно сохранить картинку в базу данных:
НовыйОбъект = Справочники.Карты.СоздатьЭлемент();
НовыйОбъект.Изображение = Новый ХранилищеЗначения(Двоичные);
НовыйОбъект.Записать();
// 3. Реквизит формы "Адрес", привязанный к Полю картинки,
// теперь содержит путь к данным в памяти сервера.
Объект.Адрес = АдресКартинки;
КонецПроцедуры
Важно понимать роль второго параметра в функции ПоместитьВоВременноеХранилище. Если мы не укажем УникальныйИдентификатор формы, платформа может удалить данные из хранилища сразу после завершения серверного вызова, и пользователь увидит пустой квадрат вместо картинки. Передавая идентификатор формы, мы гарантируем, что картинка будет доступна всё время работы с этой формой.
Если картинка уже сохранена в реквизите справочника с типом ХранилищеЗначения, нам не обязательно каждый раз вручную помещать её в хранилище. Рассмотрим альтернативный метод, который позволяет использовать стандартные механизмы платформы по работе с кэшем изображений.
Выясним, как работает метод ПолучитьНавигационнуюСсылку. Этот метод возвращает строковую ссылку на данные реквизита объекта. Если мы присвоим эту ссылку реквизиту формы, связанному с полем картинки, платформа сама извлечет данные из ХранилищеЗначения и отобразит их.
&НаСервере
Процедура ОтобразитьКартинкуИзБазы()
// Получаем навигационную ссылку на реквизит "Изображение" конкретной ссылки справочника
Объект.Адрес = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "Изображение");
КонецПроцедуры
Преимущество этого метода: нам не нужно управлять временем жизни временного хранилища. Платформа самостоятельно оптимизирует передачу данных между сервером и клиентом.
Проанализируем ситуацию, когда по HTTP приходят фотографии очень высокого разрешения. Хранение и передача таких данных в исходном виде могут значительно замедлить работу системы. Начиная с версии платформы 8.3.13, мы можем использовать объект ОбрабатываемаяКартинка (аналогично тому, как выполняется добавление водяных знаков на pdf файлы) — для этих целей есть удаление фона у картинок номенклатуры через AI.
Разберем, как уменьшить размер картинки перед её сохранением (поможет инструмент сжатия и оптимизации изображений 1С):
&НаСервере
Процедура ОбработатьИСохранитьКартинку(ДвоичныеДанные)
КартинкаОригинал = Новый Картинка(ДвоичныеДанные);
ОбрКартинка = Новый ОбрабатываемаяКартинка(КартинкаОригинал);
// Устанавливаем максимальный размер одной из сторон в 800 пикселей
ОбрКартинка.УстановитьМаксимальныйРазмер(800, 800);
// Получаем оптимизированные двоичные данные (например, в формате JPEG)
ДвоичныеОптимизированные = ОбрКартинка.ПолучитьКартинку().ПолучитьДвоичныеДанные();
// Помещаем в хранилище и на форму
Объект.Адрес = ПоместитьВоВременноеХранилище(ДвоичныеОптимизированные, УникальныйИдентификатор);
Объект.Изображение = Новый ХранилищеЗначения(ДвоичныеОптимизированные);
КонецПроцедуры
Такой подход критически важен для мобильных приложений и веб-клиентов, где пропускная способность сети может быть ограничена, а также в случаях, когда необходимо перевернуть картинку в правильную ориентацию перед показом.
Выясним важный технический нюанс: хранение двоичных данных непосредственно в основном справочнике (например, в карточке номенклатуры) считается плохой практикой в профессиональной разработке — есть готовое решение перенос хранения файлов из базы на диск. Почему это так? При любом обращении к объекту (например, просто прочитать наименование через ПолучитьОбъект()), платформа может неявно считывать всё содержимое ХранилищеЗначения, что создает избыточную нагрузку на оперативную память сервера.
Рассмотрим правильную структуру:
НоменклатураПрисоединенныеФайлы.Файл с типом ХранилищеЗначения.Иногда, несмотря на правильный код, поле картинки остается пустым. Рассмотрим основные причины и способы их диагностики:
Попытка...Исключение при создании объекта Новый Картинка(ДвоичныеДанные).РазмерКартинки установлено в значение Авторазмер или Пропорционально. При значении Реальный размер большая картинка может просто "уйти" за границы видимости маленького поля.Таким образом, мы проанализировали основные способы работы с изображениями, используя в том числе стандартные файлы графических ресурсов платформы 1С. Помните: ключ к успеху — это использование Временного хранилища с привязкой к Идентификатору формы и грамотное управление навигационными ссылками.