При программной загрузке изображений в 1С:ERP Управление предприятием разработчики нередко сталкиваются с ситуацией, когда файл успешно создается в справочнике присоединенных файлов и доступен для открытия по ссылке, однако в самой карточке номенклатуры основное изображение остается пустым. Разберем по шагам, почему возникает эта проблема и как правильно реализовать загрузку через механизмы Библиотеки стандартных подсистем (БСП).
Проанализируем типовую последовательность действий: чтобы прикрепить файл к номенклатуре, нам необходима ссылка на владельца файла. Для этого новый элемент справочника записывается в базу. Затем создается файл и возвращается ссылка на него, которая присваивается в реквизит ФайлКартинки. Если после этого не выполнить повторную запись номенклатуры, значение реквизита в базе данных останется пустым.
Рассмотрим, как зафиксировать изменения в базе данных после создания файла:
// Получаем объект номенклатуры для изменения реквизита основного изображения
НоменклатураОбъект = НоменклатураСсылка.ПолучитьОбъект();
НоменклатураОбъект.ФайлКартинки = СсылкаНаФайл;
// При необходимости отключаем версионирование и регистрацию изменений для обменов
НоменклатураОбъект.ОбменДанными.Загрузка = Истина;
НоменклатураОбъект.ДополнительныеСвойства.Вставить("СведенияОВерсииОбъекта", Ложь);
НоменклатураОбъект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов", Истина);
НоменклатураОбъект.Записать();
Обратим внимание на вызов методов. Модули с постфиксом Служебный (например, РаботаСФайламиСлужебныйВызовСервера) предназначены исключительно для внутренних механизмов подсистемы и могут изменяться от релиза к релизу без сохранения обратной совместимости. Для интеграции и прикладных задач в БСП предусмотрен общий модуль РаботаСФайлами.
Посмотрим на корректный рабочий пример добавления файла к номенклатуре:
// Помещаем полученные двоичные данные во временное хранилище
АдресФайлаВоВременномХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанныеКартинки);
// Формируем параметры файла в соответствии со стандартами БСП
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("Автор", ПараметрыСеанса.ТекущийПользователь);
ПараметрыФайла.Вставить("ВладелецФайлов", НоменклатураСсылка);
ПараметрыФайла.Вставить("ИмяБезРасширения", КраткоеИмяФайла);
ПараметрыФайла.Вставить("РасширениеБезТочки", "png");
ПараметрыФайла.Вставить("ВремяИзмененияУниверсальное", ТекущаяУниверсальнаяДата());
// Добавляем файл через штатный публичный интерфейс БСП
СсылкаНаФайл = РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, АдресФайлаВоВременномХранилище);
// Привязываем созданный файл к номенклатуре и сохраняем
НоменклатураОбъект = НоменклатураСсылка.ПолучитьОбъект();
НоменклатураОбъект.ФайлКартинки = СсылкаНаФайл;
НоменклатураОбъект.Записать();
Выясним причину, связанную с источником данных. Метод ПоместитьВоВременноеХранилище() ожидает объект типа ДвоичныеДанные или строку с путем к локальному файлу. Если исходная функция возвращает строку Base64, поток или структуру с ошибкой, во временное хранилище попадут невалидные данные. Элемент присоединенного файла будет создан, но платформа не сможет распознать содержимое как поддерживаемый графический формат.
Также важно учитывать фактический формат исходного файла: если файл имеет структуру WebP или HEIC, но сохраняется с расширением png или jpg, сторонние программы могут его отображать, а платформа 1С в элементе формы вывести не сможет.
Проанализируем проверку валидности картинки перед ее загрузкой в систему:
// Если данные переданы строкой Base64, конвертируем их
Если ТипЗнч(ИсходныеДанные) = Тип("Строка") Тогда
ДвоичныеДанныеКартинки = Base64Значение(ИсходныеДанные);
Иначе
ДвоичныеДанныеКартинки = ИсходныеДанные;
КонецЕсли;
// Проверяем, распознает ли платформа 1С формат полученных данных
ТестоваяКартинка = Новый Картинка(ДвоичныеДанныеКартинки);
Если ТестоваяКартинка.Формат() = ФорматКартинки.НеизвестныйФормат Тогда
ВызватьИсключение "Неподдерживаемый или поврежденный формат графического файла.";
КонецЕсли;
Если код добавления файла выполняется в фоновом задании, внешней обработке или в модальном диалоге, открытая в этот момент карточка номенклатуры не получает автоматического уведомления об изменении реквизитов. Поле формы не отображает актуальные данные, пока форма не будет перечитана.
Разберем действия для обновления формы на стороне клиента:
ОповеститьОбИзменении(НоменклатураСсылка).ОповеститьОбИзменении(Объект.Ссылка) и затем метод формы Прочитать() для принудительного обновления всех реквизитов и связанных навигационных ссылок.