При росте товарного каталога в любой торговой компании неизбежно возникает задача визуализации ассортимента. Когда база данных насчитывает десятки тысяч позиций (например, от 50 000 номенклатурных единиц и более), а ее текущий вес уже составляет около 60 Гб, бездумное добавление изображений может привести к катастрофическим последствиям для производительности всей системы. Пользователи начнут жаловаться на медленное открытие карточек товаров, СУБД станет потреблять критический объем оперативной памяти, а системные администраторы столкнутся со сложностями при резервном копировании.
В этой статье мы подробно разберем, какие технические проблемы возникают при хранении медиафайлов непосредственно в SQL-базе данных, проанализируем архитектурные ограничения обычных форм «1С:Предприятия» и рассмотрим три эффективных сценария решения этой задачи.
Многие начинающие разработчики совершают стандартную ошибку: они просто добавляют в карточку номенклатуры реквизит с типом ХранилищеЗначения и записывают туда бинарные данные картинок напрямую. Давайте разберем по шагам, почему этот подход является техническим тупиком для высоконагруженных баз данных:
.dt также станет регулярной проблемой.Самым надежным и общепринятым методом является хранение путей к файлам, а не самих файлов внутри СУБД. В управляемых формах этот механизм реализован на уровне типовой Библиотеки Стандартных Подсистем (БСП). Однако на обычных формах (в конфигурациях вроде «Управление торговлей 10.3», «УПП 1.3» или «Комплексная автоматизация 1.1») этот функционал придется доработать вручную.
Рассмотрим алгоритм реализации собственного механизма томов хранения файлов. Вместо записи объекта Картинка в базу данных мы будем сохранять файл на сетевом ресурсе, а в информационной базе оставлять лишь относительный путь.
Для начала создадим общий сетевой каталог, к которому у всех пользователей терминального сервера или локальной сети будет доступ на чтение и запись (например, \\ServerShare\1C_Images\). При добавлении картинки в карточку товара выполним программный перенос файла на сервер и генерацию уникального имени на основе уникального идентификатора (GUID) номенклатуры.
Ниже приведен пример кода для сохранения выбранного файла во внешний сетевой каталог:
Процедура ЗагрузитьКартинкуНаДиск(ВыбранныйФайл, НоменклатураСсылка)
СетевойКаталог = "\\ServerShare\1C_Images\";
УникальноеИмяФайла = Строка(НоменклатураСсылка.УникальныйИдентификатор()) + ".jpg";
ПолныйПутьНаСервере = СетевойКаталог + УникальноеИмяФайла;
// Копируем файл из временной папки пользователя на сетевой ресурс
Попытка
КопироватьФайл(ВыбранныйФайл, ПолныйПутьНаСервере);
// Записываем путь в реквизит карточки Номенклатуры или в регистр сведений
ОбъектНоменклатура = НоменклатураСсылка.ПолучитьОбъект();
ОбъектНоменклатура.ПутьККартинке = УникальноеИмяФайла;
ОбъектНоменклатура.Записать();
Сообщить("Картинка успешно сохранена во внешнем томе!");
Исключение
Предупреждение("Не удалось сохранить файл на сервере: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
При открытии карточки товара на обычных формах мы будем динамически считывать файл из сетевой папки и передавать его в элемент формы ПолеКартинки. Это позволит разгрузить базу данных и переложить всю работу с файлами на операционную систему.
Даже если файлы хранятся на диске, при открытии списка номенклатуры или самой карточки оригинальные изображения весом в несколько мегабайт будут серьезно нагружать локальную сеть и клиентские ПК. Пользователи будут ощущать задержки (фризы) интерфейса при перелистывании товаров.
Для решения этой проблемы необходимо внедрить двухэтапную загрузку:
Для качественного сжатия файлов на сервере под управлением ОС Windows можно воспользоваться встроенным COM-объектом работы с графикой (WIA) или консольной утилитой ImageMagick. Разберем пример использования WIA для изменения разрешения картинки перед ее сохранением:
Функция СжатьИзображение(ПутьКФайлу, ПутьКудаСохранить, МаксШирина, МаксВысота) Экспорт
Попытка
Imager = Новый COMОбъект("WIA.ImageFile");
Imager.LoadFile(ПутьКФайлу);
// Проверяем, нужно ли уменьшать картинку
Если Imager.Width > МаксШирина Или Imager.Height > МаксВысота Тогда
Process = Новый COMОбъект("WIA.ImageProcess");
Process.Filters.Add(Process.FilterInfos("Scale").FilterID);
// Настройка фильтра масштабирования
Process.Filters(1).Properties("MaximumWidth").Value = МаксШирина;
Process.Filters(1).Properties("MaximumHeight").Value = МаксВысота;
Process.Filters(1).Properties("PreserveAspectRatio").Value = Истина;
Imager = Process.Apply(Imager);
// Удаляем старый файл перед перезаписью
Если НайтиФайлы(ПутьКудаСохранить).Количество() > 0 Тогда
УдалитьФайлы(ПутьКудаСохранить);
КонецЕсли;
Imager.SaveFile(ПутьКудаСохранить);
Возврат Истина;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("СжатиеКартинок", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
Если у вашей компании есть собственный интернет-магазин, на который выгружаются все товары с качественными фотографиями, можно использовать сайт в качестве облачного хранилища картинок для 1С. Это один из самых производительных архитектурных паттернов:
https://mysite.com/uploads/goods/art_4589.jpg).Для реализации этого метода разместим на форме карточки номенклатуры элемент управления Поле HTML-документа (например, с именем ПолеHTMLПросмотра) и будем динамически загружать туда простейший HTML-код с тегом вывода картинки:
Процедура ОбновитьКартинкуНаФорме(НоменклатураСсылка)
URLКартинки = "https://mysite.com/images/goods/" + СокрЛП(НоменклатураСсылка.Артикул) + ".jpg";
// Формируем HTML-код для отображения картинки по центру с масштабированием под размеры окна
HTMLКод = "<html>
|<head>
|<style>
|body { margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; background-color: #f0f0f0; }
|img { max-width: 100%; max-height: 100%; object-fit: contain; }
|</style>
|</head>
|<body>
|<img src=""" + URLКартинки + """ onerror=""this.src='https://mysite.com/images/no-image.png';"" />
|</body>
|</html>";
ЭлементыФормы.ПолеHTMLПросмотра.УстановитьТекст(HTMLКод);
КонецПроцедуры
Использование свойства onerror в теге изображения гарантирует, что если на сайте для конкретной позиции еще нет фотографии, пользователь увидит аккуратную заглушку «Нет фото» вместо пустой страницы или стандартной ошибки браузера.
Подводя итог анализу проблемы хранения изображений в базах данных «1С:Предприятие 8» объемом от 60 Гб на обычных формах, выделим ключевые правила построения надежной архитектуры: