Как программно загрузить картинку в карточку номенклатуры в 1С:Управление торговлей 11 и Комплексная автоматизация 2.0?

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

При интеграции систем 1С с интернет-магазинами, мобильными приложениями или внешними базами данных поставщиков одной из ключевых задач становится автоматизация импорта медиаконтента. Наполнение базы номенклатуры изображениями вручную — процесс трудоемкий, поэтому разработчики часто прибегают к программной загрузке. В современных конфигурациях фирмы 1С, таких как Управление торговлей 11, Комплексная автоматизация 2.0 и ERP Управление предприятием, архитектура хранения присоединенных файлов претерпела значительные изменения по сравнению с ранними версиями платформ.

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

Метод 1. Современный стандарт: использование механизмов БСП (для актуальных версий УТ 11, КА 2.0 и ERP)

Начиная с БСП версий 2.x/3.x, крайне не рекомендуется вручную создавать элементы справочников присоединенных файлов и напрямую модифицировать связанные с ними регистры сведений. Логика современных конфигураций завязана на сложные механизмы транзакций, кэширования, проверок прав доступа и ведения истории изменений. Для корректной и безопасной загрузки файлов в систему используются экспортные методы БСП. Для изучения доступных процедур и функций библиотеки пригодится справочник по методам БСП с примерами кода.

Разберем готовый рабочий алгоритм пакетного добавления картинок из локальной папки. Процесс разделяется на клиентскую и серверную части для оптимизации трафика и производительности.

На клиенте мы получаем файлы, помещаем их во временное хранилище и передаем адреса на сервер:


&НаКлиенте
Процедура ЗагрузитьКартинкиНоменклатуры(Команда)
    
    // Путь к папке, где лежат изображения (например, "C:\Images\")
    Если Не ЗначениеЗаполнено(ПутьКПапкеКартинок) Тогда
        ВызватьИсключение "Укажите путь к каталогу с изображениями!";
    КонецЕсли;
    
    // Ищем файлы с расширением JPG в указанном каталоге
    МассивФайлов = НайтиФайлы(ПутьКПапкеКартинок, "*.jpg", Ложь);
    
    Для Каждого ТекущийФайл Из МассивФайлов Цикл
        
        // Помещаем двоичные данные файла во временное хранилище
        АдресВременногоХранилища = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ТекущийФайл.ПолноеИмя), Новый УникальныйИдентификатор);
        
        // Передаем данные на сервер для обработки и привязки к номенклатуре
        // Имя файла без расширения используется в качестве кода или артикула для поиска товара
        ПоместитьКартинкуНаСервере(ТекущийФайл.ИмяБезРасширения, ТекущийФайл.Расширение, ТекущийФайл.ПолучитьУниверсальноеВремяИзменения(), АдресВременногоХранилища);
        
    КонецЦикла;
    
КонецПроцедуры

На сервере мы находим номенклатуру по ключевому реквизиту (например, артикулу или коду), подготавливаем структуру параметров для БСП и вызываем метод добавления файла:


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

Метод 2. Прямая программная запись (для старых релизов УТ 11.0 / УТ 11.1)

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

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


Процедура ЗагрузитьКартинкуНапрямуюССайта(НоменклатураОбъект, ИмяКартинкиНаСайте)
    
    КартинкаСсылка = Справочники.НоменклатураПрисоединенныеФайлы.ПустаяСсылка();
    
    // Задаем параметры HTTP-соединения с сайтом-источником
    Соединение = Новый HTTPСоединение("адрес_сайта_поставщика.ru");
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла(".jpg");
    
    Попытка
        // Скачиваем файл во временный каталог на диске сервера/клиента
        Соединение.Получить("/images/" + ИмяКартинкиНаСайте, ИмяВременногоФайла);
    Исключение
        ЗаписьЖурналаРегистрации("ЗагрузкаКартинок", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // Создаем элемент справочника присоединенных файлов
    КартинкаОбъект = Справочники.НоменклатураПрисоединенныеФайлы.СоздатьЭлемент();
    КартинкаОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе;
    КартинкаОбъект.Наименование = НоменклатураОбъект.Код;
    КартинкаОбъект.ВладелецФайла = НоменклатураОбъект.Ссылка;
    КартинкаОбъект.Расширение = "jpg";
    КартинкаОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
    
    // Читаем скачанный файл в объект Картинка и получаем двоичные данные для ХранилищаЗначения
    К1 = Новый Картинка(ИмяВременногоФайла, Истина);
    КартинкаОбъект.ФайлХранилище = Новый ХранилищеЗначения(К1.ПолучитьДвоичныеДанные());
    
    ФайлК = Новый Файл(ИмяВременногоФайла);
    КартинкаОбъект.Размер = ФайлК.Размер;
    
    // Записываем карточку файла в базу данных, чтобы получить ссылку
    КартинкаОбъект.Записать();
    КартинкаСсылка = КартинкаОбъект.Ссылка;
    
    // Заполняем служебный регистр сведений "ПрисоединенныеФайлы", без этого платформа выдаст ошибку
    КартинкаСохранить = РегистрыСведений.ПрисоединенныеФайлы.СоздатьНаборЗаписей();
    КартинкаСохранить.Отбор.ПрисоединенныйФайл.Установить(КартинкаСсылка);
    
    НовыйФайл = КартинкаСохранить.Добавить();
    НовыйФайл.ПрисоединенныйФайл = КартинкаСсылка;
    НовыйФайл.ХранимыйФайл = КартинкаОбъект.ФайлХранилище;
    
    // Записываем набор записей регистра
    КартинкаСохранить.Записать();
    
    // Связываем файл с номенклатурой
    НоменклатураОбъект.ФайлКартинки = КартинкаСсылка;
    НоменклатураОбъект.Записать();
    
    // Удаляем временный файл с диска
    УдалитьФайлы(ИмяВременногоФайла);
    
КонецПроцедуры

Анализ проблем и ошибок при программной работе с картинками

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

  1. Ошибка "Поле объекта недоступно для записи (ФайлКартинки)"

    Выясним причину этой ошибки. Часто начинающие разработчики пытаются внедрить код загрузки прямо в форму элемента номенклатуры и пишут конструкцию вида Объект.ФайлКартинки = СсылкаНаФайл на клиенте. В управляемых формах реквизит Объект является типом ДанныеФормыСтруктура, и некоторые его поля могут быть аппаратно заблокированы от интерактивного изменения бизнес-логикой формы.

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

  2. Проблема загрузки в новых (еще не записанных) элементах номенклатуры

    Невозможно привязать присоединенный файл к номенклатуре, которая еще не существует в базе физически. У незаписанного элемента значение Номенклатура.Ссылка является пустым, а значит, поле ВладелецФайла у присоединенного файла заполнить не удастся.

    Решение: Сначала выполните метод Записать() для новой номенклатуры, получите ссылку на элемент базы данных и только после этого инициализируйте параметры добавления изображения.

  3. Проблема "В томах на диске" (Файлы сохраняются в базу, но не на диск)

    Если в настройках программы включено хранение присоединенных файлов в томах на диске, ручной код (Метод 2) продолжит принудительно записывать бинарные данные непосредственно в СУБД (в реквизит ФайлХранилище), раздувая базу данных. При этом на сетевом диске файлы создаваться не будут.

    Решение: Использование БСП-метода ПрисоединенныеФайлы.ДобавитьПрисоединенныйФайл() полностью решает эту проблему. Алгоритмы БСП сами анализируют константы настроек системы. Если включено дисковое хранение, библиотека автоматически извлечет файл из временного хранилища, переименует его по уникальному GUID, запишет в физический сетевой каталог тома и сформирует правильные относительные пути в карточке файла информационной базы.

  4. Оптимизация размеров и форматов изображений

    Массовая загрузка файлов поставщиков "как есть" часто приводит к быстрому расходу дискового пространства. Фотографии высокого разрешения (например, 4000x3000 пикселей) не нужны для карточек товаров. Перед загрузкой рекомендуется выполнять конвертацию или программное сжатие.

    Платформа 1С поддерживает встроенный метод Картинка.Преобразовать(), с помощью которого можно изменить формат тяжелых картинок в сжатый JPEG:

    
    ИсходнаяКартинка = Новый Картинка(ПутьКФайлу);
    Если ИсходнаяКартинка.Формат() <> ФорматКартинки.JPEG Тогда
        КонвертированнаяКартинка = ИсходнаяКартинка.Преобразовать(ФорматКартинки.JPEG);
        ДвоичныеДанныеДляСохранения = КонвертированнаяКартинка.ПолучитьДвоичныеДанные();
    КонецЕсли;
    

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

← На главную