Как правильно загрузить картинку в номенклатуру и отобразить ее на форме в 1С?

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

Загрузка графических файлов (изображений товаров, сертификатов, сканов документов) в базу данных 1С — это классическая задача, с которой сталкивается практически каждый разработчик. На первый взгляд процесс кажется простым: взяли файл с диска, поместили в реквизит справочника и вывели на форму. Однако при реализации программисты часто сталкиваются с техническими нюансами клиент-серверного взаимодействия, особенностями работы с типом данных ХранилищеЗначения и механизмами отображения картинок в управляемом интерфейсе.

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

Анализ и оптимизация процесса загрузки файла

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


&НаКлиенте
Процедура ЗагрузитьКартинки(Строка)
    
    АдресНов = "C:\Files\" + Строка.Артикул + ".jpg";
    КопироватьФайл(Строка.Изображение, АдресНов);
    
    Картинка = Новый Картинка(Строка(АдресНов));
    Строка.БиДанные = Картинка.ПолучитьДвоичныеДанные();
    
КонецПроцедуры

Выясним причину, почему этот код не является оптимальным:

  1. Лишние дисковые операции: Метод КопироватьФайл выполняет физическое дублирование файла на жестком диске. Если картинок тысячи, это создает ненужную нагрузку на дисковую подсистему и засоряет временные папки.
  2. Избыточное создание объектов: Конструктор Новый Картинка() инициализирует полноценный графический объект платформы в памяти. Если наша задача — просто прочитать файл и записать его в базу, декодировать изображение средствами платформы на клиенте нет никакой необходимости.
  3. Ограничения веб-клиента: Работа с локальными путями файлов напрямую через конструкторы на клиенте не будет работать в веб-клиенте (при запуске 1С через браузер) из соображений безопасности браузеров.

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


&НаКлиенте
Процедура ЗагрузитьКартинкуОптимально(Строка)
    
    ПутьКФайлу = Строка.Изображение; // Здесь хранится путь, например, "C:\Temp\photo.jpg"
    
    Если ФайлСуществует(ПутьКФайлу) Тогда
        // Получаем двоичные данные напрямую из файла
        Строка.БиДанные = Новый ДвоичныеДанные(ПутьКФайлу);
    КонецЕсли;
    
КонецПроцедуры

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


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

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

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

Преобразование двоичных данных в ХранилищеЗначения и запись в БД

Для хранения файлов, картинок и документов в реквизитах объектов 1С используется специальный тип данных — ХранилищеЗначения. Этот объект предназначен для сжатия и сериализации любых данных (включая структуры, массивы и двоичные файлы) перед их записью в СУБД.

Часто возникает вопрос: что именно передавать в конструктор ХранилищеЗначения — сам объект Картинка или двоичные данные файла? На практике рекомендуется сохранять именно двоичные данные. Это универсальный формат, который не зависит от графического движка платформы и гарантирует, что файл запишется в базу "байт в байт" без потери метаданных или изменения качества изображения.

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


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

Обратите внимание на параметр Новый СжатиеДанных(9) в конструкторе ХранилищеЗначения. Платформа 1С позволяет регулировать уровень сжатия данных при сохранении в базу. Значение "9" обеспечивает максимальное сжатие, что позволяет экономить дисковое пространство на сервере баз данных.

Как правильно отобразить картинку на управляемой форме

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

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

Существует два правильных способа передать этот адрес на форму в зависимости от сценария работы.

Способ 1. Получение прямой навигационной ссылки из базы данных

Если картинка уже успешно сохранена в реквизите объекта базы данных (например, в реквизите "Фото" справочника Номенклатура), нам вообще не нужно извлекать данные на сервере и передавать их в память. Мы можем сгенерировать прямую навигационную ссылку к реквизиту СУБД. Это самый быстрый и производительный способ.


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

Полученный адрес будет иметь вид e1cib/data/Справочник.Номенклатура.Фото?ref=.... Платформа 1С самостоятельно считает двоичные данные из СУБД в фоновом режиме и отобразит их в элементе формы.

Способ 2. Использование временного хранилища

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


&НаСервере
Процедура ПоместитьКартинкуВоВременноеХранилище(ДвоичныеДанныеКартинки)
    
    // Помещаем данные во временное хранилище, привязывая к уникальному идентификатору формы
    АдресКартинкиНаФорме = ПоместитьВоВременноеХранилище(ДвоичныеДанныеКартинки, ЭтаФорма.УникальныйИдентификатор);
    
КонецПроцедуры

Использование параметра ЭтаФорма.УникальныйИдентификатор крайне важно. Это гарантирует, что временный файл будет автоматически удален из оперативной памяти сервера сразу после того, как пользователь закроет данную форму номенклатуры. Это предотвращает утечки памяти на сервере 1С:Предприятие.

Архитектурные рекомендации по хранению файлов в 1С

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

Рассмотрим лучшие архитектурные практики, которые рекомендуется применять при разработке:

← На главную