Хранение изображений непосредственно в базе данных «1С:Предприятия» — одна из главных причин лавинообразного роста размера базы данных. Это приводит к замедлению резервного копирования, снижению производительности всей системы и дополнительным затратам на серверное оборудование. Отличной альтернативой является хранение картинок на внешнем веб-сервере или S3-хранилище, в то время как в самой 1С сохраняются только текстовые ссылки (URL) на эти файлы.
В этой статье мы подробно разберем, как организовать хранение медиафайлов на сайте, как корректно и безопасно отображать их в формах 1С (как в обычных, так и в управляемых формах), а также рассмотрим механизмы оптимизации загрузки, такие как асинхронность и локальное кэширование.
Прежде чем переходить к написанию кода, определим общую архитектурную схему решения. Вместо хранения двоичных данных в стандартных таблицах базы данных (например, в справочнике Файлы или табличных частях номенклатуры) мы выполняем следующие действия:
Номенклатура (или в отдельный связанный справочник/регистр сведений) строковый реквизит, например, СсылкаНаКартинку с длиной от 250 до 1000 символов.https://mysite.ru/images/goods/item_1025.jpg).Самый простой и не требующий сложных алгоритмов способ отображения картинки по URL — это использование стандартного элемента формы «Поле HTML-документа». Этот метод отлично работает как на обычных формах (начиная с платформы 8.2), так и на управляемых формах 8.3.
Разберем по шагам, как настроить отображение через HTML:
Строка и назовем его, например, АдресКартинкиHTML.<img>, где атрибут src указывает на наш URL.Рассмотрим пример кода для инициализации поля HTML-документа:
&НаСервере
Процедура ОбновитьКартинкуНаФормеНаСервере()
СсылкаНаКартинку = Объект.СсылкаНаКартинку; // Наш реквизит с URL
Если ЗначениеЗаполнено(СсылкаНаКартинку) Тогда
// Формируем простейший HTML-контейнер с масштабированием изображения под размеры поля
СтрокаHTML = "<html>
|<body style=""margin:0; padding:0; overflow:hidden; background-color: #F0F0F0;"">
|<img src=""" + СсылкаНаКартинку + """ style=""width:100%; height:100%; object-fit: contain;"" />
|</body>
|</html>";
Иначе
// Отображаем пустую заглушку, если ссылка отсутствует
СтрокаHTML = "<html><body style=""margin:0; padding:0;""><p style=""text-align:center; padding-top:20%; color:gray;"">Картинка отсутствует</p></body></html>";
КонецЕсли;
АдресКартинкиHTML = СтрокаHTML;
КонецПроцедуры
Преимущества метода: простота реализации, автоматическая обработка сетевых протоколов встроенным браузером операционной системы, нет необходимости сохранять файлы на жесткий диск пользователя.
Недостатки: зависимость от настроек системного браузера, возможные проблемы с контекстным меню веб-страницы при клике на поле и отсутствие прямого контроля над кэшированием.
Более профессиональным и «чистым» с точки зрения интерфейса 1С является отображение картинки через стандартный элемент управления «Поле картинки». Для этого нам потребуется скачать файл во временную папку компьютера пользователя, поместить его во временное хранилище и привязать к элементу формы.
Важное предупреждение: Ни в коем случае нельзя выполнять скачивание файлов из интернета синхронно в основном потоке (например, в процедуре ПриСозданииНаСервере или ПриОткрытии). Если внешний сайт окажется недоступен или будет долго отвечать на запросы, форма карточки товара зависнет, заблокировав работу пользователя. Интерфейс 1С «зависнет» до истечения таймаута соединения.
Для решения этой проблемы мы применим асинхронные методы платформы 1С 8.3. Разберем этот алгоритм по шагам:
&НаКлиенте
Асинх Процедура ПриОткрытии(Отказ)
Ожидать ЗагрузитьКартинкуАсинхронно();
КонецПроцедуры
&НаКлиенте
Асинх Функция ЗагрузитьКартинкуАсинхронно()
// Ссылка на элемент формы "Поле картинки", привязанный к строковому реквизиту "ПутьККартинке"
Если Не ЗначениеЗаполнено(Объект.СсылкаНаКартинку) Тогда
ПутьККартинке = ""; // Сбрасываем картинку, если ссылки нет
Возврат;
КонецЕсли;
// Задаем путь для временного файла на локальном диске
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("png");
Попытка
// Используем встроенный асинхронный метод копирования файлов по HTTP/HTTPS протоколам
Ожидать КопироватьФайлАсинх(Объект.СсылкаНаКартинку, ИмяВременногоФайла);
// Помещаем файл во временное хранилище для отображения на форме
АдресВременногоХранилища = Ожидать ПоместитьВоВременноеХранилищеАсинх(Новый ДвоичныеДанные(ИмяВременногоФайла));
// Передаем адрес реквизиту формы, связанному с Полем Картинки
ПутьККартинке = АдресВременногоХранилища;
// Удаляем временный файл с диска после его помещения в память
УдалитьФайлы(ИмяВременногоФайла);
Исключение
// Если сайт упал или ссылка битая - перехватываем ошибку без зависания интерфейса
ЗаписатьЛогОшибки(ОписаниеОшибки());
ПутьККартинке = "КартинкаНеДоступна"; // Ссылка на картинку-заглушку в макете
КонецПопытки;
КонецФункции
При таком подходе карточка товара открывается мгновенно. Пользователь сразу видит все текстовые реквизиты и может работать с ними, в то время как картинка загружается в фоновом режиме на клиенте. Если сайт недоступен, 1С просто перехватит ошибку в блоке Исключение и не нарушит работу оператора.
Постоянное скачивание одной и той же картинки по сети при каждом открытии карточки товара или при перемещении по динамическому списку создает колоссальную нагрузку на веб-сервер и сетевой канал офиса. Чтобы этого избежать, мы настоятельно рекомендуем разработать простой механизм локального кэширования файлов на компьютерах пользователей.
Рассмотрим логику работы кэша:
Проанализируем пример кода с функцией кэширования:
&НаКлиенте
Функция ПолучитьКартинкуИзКэшаИлиСети(УРЛАдрес) Экспорт
Если Не ЗначениеЗаполнено(УРЛАдрес) Тогда
Возврат "";
КонецЕсли;
// Шаг 1: Создаем каталог кэша в папке временных файлов пользователя
КаталогКэша = КаталогВременныхФайлов() + "1C_Image_Cache\";
СоздатьКаталог(КаталогКэша);
// Шаг 2: Получаем уникальное имя файла по хэшу URL-адреса
ИмяФайлаКэша = КаталогКэша + ПолучитьИмяФайлаПоХэшу(УРЛАдрес) + ".jpg";
ФайлНаДиске = Новый Файл(ИмяФайлаКэша);
// Шаг 3: Проверка наличия файла в кэше
Если ФайлНаДиске.Существует() Тогда
Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайлаКэша));
КонецЕсли;
// Шаг 4: Если в кэше нет — скачиваем из сети
Попытка
КопироватьФайл(УРЛАдрес, ИмяФайлаКэша);
Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайлаКэша));
Исключение
// В случае ошибки возвращаем пустую строку или заглушку "Файл не найден"
Возврат "";
КонецПопытки;
КонецФункции
&НаКлиенте
Функция ПолучитьИмяФайлаПоХэшу(СтрокаURL)
// Функция преобразует URL в хэш MD5 для уникального и валидного имени файла
Хеш = Новый ХешированиеДанных(ХешФункция.MD5);
Хеш.Добавить(СтрокаURL);
Возврат Строка(Хеш.ХешСумма);
КонецФункции
Для предотвращения чрезмерного разрастания папки кэша на диске пользователя рекомендуется настроить регламентное задание (или процедуру при завершении работы системы), которое будет удалять файлы из каталога кэша, если дата их изменения превышает, к примеру, 14 дней.
В первом сообщении темы автор упоминает необходимость загрузки данных из внешних Excel-файлов. При импорте товаров из Excel, содержащего ссылки на изображения, ни в коем случае нельзя скачивать файлы интерактивно в цикле обработки строк на клиенте. Процесс импорта тысяч позиций заблокирует сеанс работы пользователя на несколько часов.
Правильным подходом будет перенос задачи импорта картинок в фоновое задание на сервере:
Номенклатура с заполненным текстовым полем СсылкаНаКартинку.В обсуждениях на форумах часто предлагается хранить картинки в обычных папках веб-сайта и обмениваться ими по протоколу FTP. В современных реалиях разработки этот метод считается устаревшим из-за низкой безопасности и слабой масштабируемости.
Для хранения файлов вне базы 1С сегодня рекомендуется использовать современные S3-совместимые объектные облачные хранилища (например, Yandex Object Storage, MinIO, AWS S3 и др.). Интеграция 1С с объектными облаками предоставляет важные преимущества:
Внедрение одной из предложенных методик позволит вам сохранить базу данных «1С:Предприятия» компактной и быстрой, а пользователям обеспечит комфортную и оперативную работу с изображениями товаров без каких-либо зависаний интерфейса программы.