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

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

При разработке обработок по оптимизации, сжатию или пакетной загрузке изображений номенклатуры в современных конфигурациях 1С (таких как «1С:Управление торговлей 11», «1С:ERP» или «1С:Комплексная автоматизация») начинающие программисты часто сталкиваются с аппаратной ошибкой записи данных. Попытка напрямую перезаписать реквизит хранилища приводит к ошибке доступа или к тому, что изменения попросту не сохраняются в базе данных.

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

Выясняем причину: почему ругается 1С при попытке записи

Рассмотрим исходную ситуацию. У нас есть код, в котором разработчик пытается записать сжатую картинку обратно в номенклатуру:


ИзмененнаяПозиция = Выборка.Ссылка.ПолучитьОбъект();
МояКартинка = Новый Картинка(ИмяФайлa3);
Хран = Новый ХранилищеЗначения(МояКартинка);
ИзмененнаяПозиция.ФайлКартинки.ФайлХранилище = Хран; // Точка останова и ошибка
ИзмененнаяПозиция.Записать();

Проанализируем этот участок кода. Здесь кроется фундаментальная ошибка понимания объектной модели платформы 1С. Разработчик получил объект номенклатуры в переменную ИзмененнаяПозиция. Реквизит номенклатуры ФайлКартинки является ссылкой на элемент другого справочника — обычно это СправочникСсылка.НоменклатураПрисоединенныеФайлы.

Когда выполняется выражение ИзмененнаяПозиция.ФайлКартинки.ФайлХранилище = Хран, программа пытается напрямую изменить реквизит у ссылки, а не у объекта. В 1С:Предприятии свойства объектов, доступные через точку от ссылки, открыты только для чтения. Чтобы изменить данные присоединенного файла, нам необходимо получить непосредственный объект этого файла.

Решение №1: Исправление объектного пути (классический метод)

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

  1. Получаем ссылку на файл картинки из выборки.
  2. Проверяем, заполнена ли эта ссылка.
  3. Получаем объект присоединенного файла с помощью метода ПолучитьОбъект().
  4. Записываем новое ХранилищеЗначения в соответствующий реквизит объекта присоединенного файла.
  5. Записываем сам объект присоединенного файла.

Посмотрим на пример реализации этого алгоритма:


// Проверяем, заполнена ли ссылка на картинку у номенклатуры
Если ЗначениеЗаполнено(Выборка.ФайлКартинки) Тогда
    
    // Получаем ОБЪЕКТ присоединенного файла, а не номенклатуры!
    ОбъектФайлаКартинки = Выборка.ФайлКартинки.ПолучитьОбъект();
    
    Если ОбъектФайлаКартинки <> Неопределено Тогда
        // Создаем объект Картинка из файла на диске
        НоваяКартинка = Новый Картинка(ИмяФайла2);
        
        // Помещаем картинку в ХранилищеЗначения
        НовоеХранилище = Новый ХранилищеЗначения(НоваяКартинка);
        
        // Записываем хранилище в реквизит объекта файла
        ОбъектФайлаКартинки.ФайлХранилище = НовоеХранилище;
        
        // Сохраняем изменения присоединенного файла в базе данных
        ОбъектФайлаКартинки.Записать();
        
        Сообщить("Изображение успешно обновлено для номенклатуры: " + Выборка.Ссылка);
    КонецЕсли;
    
КонецЕсли;

Этот метод исправит ошибку записи, но у него есть ряд критических недостатков, если мы работаем в современных конфигурациях на базе БСП (например, УТ 11).

Решение №2: Современный подход с использованием БСП

В конфигурации «1С:Управление торговлей 11» файлы не всегда хранятся непосредственно в базе данных в реквизите ФайлХранилище. В настройках системы может быть включена опция «Хранить файлы в томах на диске». В этом случае физические файлы сохраняются в сетевой папке на сервере, а в базе хранятся лишь пути к ним. Если вы попытаетесь перезаписать ФайлХранилище напрямую, файлы на диске не обновятся, и система покажет пользователю старое изображение из кэша или выдаст ошибку.

Также, в современных версиях БСП двоичные данные могут кэшироваться в регистре сведений ДвоичныеДанныеФайлов. Чтобы избежать рассинхронизации данных, мы должны использовать штатные механизмы подсистемы «Работа с файлами».

Рассмотрим подробнее программный код, который корректно обновит картинку независимо от того, где она хранится — в базе данных или на диске:


// 1. Создаем двоичные данные из нового (сжатого) файла изображения
ДвоичныеДанныеНовойКартинки = Новый ДвоичныеДанные(ИмяФайла2);

// 2. Помещаем эти данные во временное хранилище
АдресВременногоХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеНовойКартинки);

// 3. Формируем структуру с параметрами файла для БСП
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("АдресФайлаВоВременномХранилище", АдресВременногоХранилища);
ПараметрыФайла.Вставить("ДатаМодификацииУниверсальная", УниверсальноеВремя(ТекущаяДата()));

// 4. Ссылка на присоединенный файл номенклатуры
СсылкаНаФайл = Выборка.ФайлКартинки;

Если ЗначениеЗаполнено(СсылкаНаФайл) Тогда
    // Вызываем стандартный метод БСП для перезаписи файла
    РаботаСФайлами.ОбновитьФайл(СсылкаНаФайл, ПараметрыФайла);
    Сообщить("Файл успешно обновлен через БСП для: " + Выборка.Ссылка);
КонецЕсли;

Использование метода РаботаСФайлами.ОбновитьФайл гарантирует, что система автоматически определит место хранения картинки, запишет её в нужный том на диске (если используются тома), обновит размер файла в карточке и очистит старый кэш у пользователей.

Решение №3: Избавляемся от сторонних программ (сжатие силами 1С)

В исходном коде автора для сжатия изображений запускаются внешние утилиты PhotoResize400.exe и JPGCLN32.EXE через вызов команды ЗапуститьПриложение. Такой подход имеет серьезные минусы: он привязан к операционной системе Windows, требует наличия стороннего софта на сервере или клиенте и значительно замедляет работу системы.

Начиная с версии платформы 1С:Предприятие 8.3.14, разработчикам доступен мощный встроенный инструмент — объект ОбрабатываемаяКартинка. Он позволяет сжимать, масштабировать, обрезать и конвертировать изображения непосредственно в коде 1С.

Проанализируем ситуацию и напишем полностью автономный код, который сжимает исходное изображение номенклатуры до нужных размеров (например, до ширины в 600 пикселей с оптимизацией качества JPEG) и сразу обновляет его в системе:


// Получаем двоичные данные исходной картинки из базы через БСП
ДвоичныеДанныеИсходные = РаботаСФайлами.ДвоичныеДанныеФайла(Выборка.ФайлКартинки);

Если ТипЗнч(ДвоичныеДанныеИсходные) = Тип("ДвоичныеДанные") Тогда
    
    // Создаем объект Картинка
    ИсходнаяКартинка = Новый Картинка(ДвоичныеДанныеИсходные);
    
    // Инициализируем инструмент обработки картинок платформы 1С
    ОбработкаИзображения = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
    
    // Пропорционально уменьшаем картинку до ширины 600 пикселей (высота определится сама)
    ОбработкаИзображения.УстановитьРазмер(600, Неопределено);
    
    // Получаем обработанную картинку
    СжатаяКартинка = ОбработкаИзображения.ПолучитьКартинку();
    
    // Получаем двоичные данные сжатого изображения в формате JPEG с качеством 75%
    ДвоичныеДанныеСжатые = СжатаяКартинка.ПолучитьДвоичныеДанные("image/jpeg", 75);
    
    // Помещаем новые сжатые данные во временное хранилище
    АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеСжатые);
    
    // Готовим структуру для обновления БСП
    ПараметрыОбновления = Новый Структура;
    ПараметрыОбновления.Вставить("АдресФайлаВоВременномХранилище", АдресХранилища);
    ПараметрыОбновления.Вставить("ДатаМодификацииУниверсальная", УниверсальноеВремя(ТекущаяДата()));
    
    // Обновляем файл изображения в системе
    РаботаСФайлами.ОбновитьФайл(Выборка.ФайлКартинки, ПараметрыОбновления);
    
    Сообщить("Изображение для " + Выборка.Ссылка + " успешно сжато средствами платформы 1С.");
    
КонецЕсли;

Подведем итоги

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

← На главную