Как реализовать загрузку и отображение картинки в справочнике 1С 8.3 на управляемых формах?

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

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

Постановка задачи и структура данных

Для начала проанализируем ситуацию. Предположим, у нас есть справочник БлаготворительныеОрганизации. Для работы с изображениями нам понадобятся следующие реквизиты:

  1. Картинка (тип ХранилищеЗначения) — здесь будут физически храниться двоичные данные изображения в базе данных.
  2. СсылкаНаКартинку (тип Строка) — в этом реквизите мы будем хранить имя файла с расширением для информативности.

На самой форме справочника нам необходимо создать реквизит формы (не путать с реквизитом объекта), который мы назовем Логотип. Его тип должен быть Строка. Именно этот строковый реквизит мы разместим на форме и установим ему вид Поле картинки. В нем будет храниться либо адрес временного хранилища (пока объект не записан), либо навигационная ссылка на данные в базе.

Шаг 1: Инициализация выбора файла на клиенте

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


&НаКлиенте
Процедура ВыбратьЛоготип(Команда)
    
    // Настройка диалога выбора файла
    ДиалогОткрытия = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ДиалогОткрытия.ПолноеИмяФайла = "";
    ДиалогОткрытия.Фильтр = "Все картинки (*.bmp;*.jpg;*.jpeg;*.png;)|*.bmp;*.jpg;*.jpeg;*.png;";
    ДиалогОткрытия.МножественныйВыбор = Ложь;
    ДиалогОткрытия.Заголовок = "Выберите логотип организации";
    
    // Подготовка описания оповещения для обработки выбора
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтаФорма);
    ДиалогОткрытия.Показать(ОписаниеОповещения);
    
КонецПроцедуры

Шаг 2: Помещение файла во временное хранилище

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


&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныеФайлы = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ПутьКФайлу = ВыбранныеФайлы[0];
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПомещенияВХранилище", ЭтаФорма);
    
    // Помещаем файл во временное хранилище, привязывая его к идентификатору формы
    НачатьПомещениеФайла(ОписаниеОповещения, , ПутьКФайлу, Ложь, УникальныйИдентификатор);
    
КонецПроцедуры

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

Шаг 3: Сохранение данных на сервере

Теперь разберем, как данные попадают в базу. Основная работа происходит в обработчике ПередЗаписьюНаСервере. Мы проверяем, является ли значение в реквизите Логотип адресом временного хранилища. Если да, значит, пользователь загрузил новую картинку, и её нужно упаковать в ХранилищеЗначения.


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

Шаг 4: Отображение картинки при открытии и после записи

Посмотрим на пример того, как сделать так, чтобы картинка не «пропадала» при закрытии и повторном открытии карточки справочника. Для этого нам нужно преобразовать данные из типа ХранилищеЗначения обратно в навигационную ссылку, которую понимает Поле картинки. Это необходимо делать в нескольких местах: при создании формы, при чтении объекта и сразу после записи.


&НаСервере
Процедура ОбновитьОтображениеЛоготипа()
    
    // Если объект уже записан в базе, получаем ссылку на его реквизит
    Если Не Объект.Ссылка.Пустая() Тогда
        Логотип = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "Картинка");
    КонецЕсли;
    
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ОбновитьОтображениеЛоготипа();
КонецПроцедуры

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    ОбновитьОтображениеЛоготипа();
КонецПроцедуры

&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // После записи обновляем ссылку, чтобы она указывала на актуальные данные в БД
    ОбновитьОтображениеЛоготипа();
КонецПроцедуры

Важные технические нюансы

Рассмотрим подробнее ошибки, которые часто совершают разработчики. Например, попытка создать объект Новый Картинка(ПутьКФайлу) на клиенте. В управляемых формах 1С прямой доступ к файлам ограничен в целях безопасности. Поэтому правильный путь — использование временного хранилища через НачатьПомещениеФайла.

Также проанализируем ситуацию с реквизитом СсылкаНаКартинку. Если вы хотите отображать имя файла на форме, убедитесь, что вы обращаетесь к Объект.СсылкаНаКартинку, а не к элементам формы напрямую. Присваивание значения должно происходить именно реквизиту объекта, чтобы платформа знала, что данные нужно сохранить в таблицу базы данных.

Основные рекомендации:

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

← На главную