Загрузка изображений — одна из самых частых задач при разработке в среде 1С:Предприятие 8.3. Будь то фотография сотрудника, логотип компании или изображение товара, логика реализации остается схожей. Однако начинающие разработчики часто сталкиваются с техническими трудностями: от ошибок «недостаточно памяти» до некорректного отображения картинки на форме. В этой статье мы подробно разберем, как правильно реализовать этот функционал, проанализируем ошибки и рассмотрим современные методы оптимизации.
Прежде всего, нам необходимо подготовить место для хранения данных. Рассмотрим ситуацию на примере справочника Сотрудники. Проанализируем, какие объекты нам потребуются:
ФайлКартинки. Тип данных должен быть ХранилищеЗначения. Этот тип позволяет хранить любые бинарные данные (картинки, документы, архивы) непосредственно в базе данных или внешних томах.ПутьКФайлу (или СсылкаНаКартинку). Важно: тип этого реквизита должен быть Строка (неограниченной длины). Именно в этот строковый реквизит мы будем помещать временный адрес картинки для ее визуализации.ПутьКФайлу на форму и установим для него Вид — Поле картинки. Это позволит платформе интерпретировать строку как ссылку на изображение.Разберем программную логику. Нам нужно организовать диалог выбора файла и передачу его во временное хранилище. Рассмотрим пример кода, использующий асинхронный подход, который является стандартом для современных конфигураций.
&НаКлиенте
Процедура ЗагрузитьФотографию(Команда)
// Настроим диалог выбора файла
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Изображения (*.jpg;*.png)|*.jpg;*.png";
Диалог.Заголовок = "Выберите фотографию сотрудника";
// Используем описание оповещения для обработки выбора
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы = Неопределено Тогда
Возврат;
КонецЕсли;
// Помещаем файл во временное хранилище
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , , ВыбранныеФайлы[0], УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Результат Тогда
// Записываем адрес временного хранилища в реквизит формы для отображения
ПутьКФайлу = Адрес;
ЭтаФорма.Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
В данном примере мы используем метод НачатьПомещениеФайлаНаСервер. Это позволяет избежать зависания интерфейса при загрузке больших файлов и корректно работает в веб-клиенте.
После того как файл попал во временное хранилище, его нужно окончательно привязать к объекту справочника. Наилучшее место для этого — серверная процедура ПередЗаписьюНаСервере. Выясним, как правильно извлечь данные и упаковать их в ХранилищеЗначения.
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Проверяем, является ли путь адресом во временном хранилище
Если ЭтоАдресВременногоХранилища(ПутьКФайлу) Тогда
// Получаем бинарные данные из хранилища
ДанныеКартинки = ПолучитьИзВременногоХранилища(ПутьКФайлу);
// Помещаем данные в реквизит объекта
ТекущийОбъект.ФайлКартинки = Новый ХранилищеЗначения(ДанныеКартинки);
// После записи обновляем путь на постоянную навигационную ссылку
// Это нужно, чтобы картинка не пропала после очистки временного хранилища
КонецЕсли;
КонецПроцедуры
Часто программисты сталкиваются с тем, что при сохранении или загрузке система выдает ошибку памяти. Проанализируем основные причины этой ситуации:
Чтобы база данных не "раздувалась" от тяжелых фотографий, рассмотрим возможность предварительного сжатия изображений на сервере перед сохранением. Проанализируем пример кода для изменения размера картинки:
&НаСервере
Функция СжатьИзображение(ДанныеИзображения)
КартинкаОбъект = Новый Картинка(ДанныеИзображения);
// Если картинка слишком большая, можно ее обработать
// В 1С 8.3 для этого часто используют внешние компоненты или
// системные возможности преобразования форматов.
// Пример простого получения картинки в формате PNG для унификации:
КартинкаPNG = КартинкаОбъект.Преобразовать(ФорматКартинки.PNG);
Возврат КартинкаPNG.ПолучитьДвоичныеДанные();
КонецФункции
Помимо сжатия, в профессиональных решениях (например, на базе Библиотеки стандартных подсистем — БСП) рекомендуется:
Чтобы картинка отображалась каждый раз при открытии карточки сотрудника, нам нужно инициализировать наш строковый реквизит в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Генерируем навигационную ссылку на реквизит ХранилищеЗначения
Если НЕ Объект.Ссылка.Пустая() Тогда
ПутьКФайлу = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ФайлКартинки");
КонецЕсли;
КонецПроцедуры
Таким образом, мы обеспечиваем надежный цикл работы с графическими данными: от выбора файла пользователем до долгосрочного хранения и быстрой визуализации. Помните, что работа с ХранилищеЗначения требует внимательности к контексту (Клиент/Сервер) и понимания жизненного цикла временного хранилища.