Как сохранить картинку номенклатуры из информационной базы 1С на диск?

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

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

Причины ошибки «Значение не является значением объектного типа (Записать)»

Выясним причину популярной ошибки, с которой сталкиваются разработчики при попытке выгрузить файл. Ошибка возникает в случае, если реквизит хранилища (например, ФайлХранилище) считывается некорректно или возвращает не сам объект бинарных данных, а значение Undefined (Неопределено) или вложенное ХранилищеЗначения.

Если хранилище содержит сам объект типа Картинка, то прямой вызов метода .Получить().Записать() вызовет ошибку, так как из хранилища извлекается не объект ДвоичныеДанные, а внутреннее представление или неопределенное значение (например, если файлы хранятся во внешних томах на сервере).

Способ 1. Извлечение двоичных данных через ХранилищеЗначения

Проанализируем базовый вариант выгрузки, когда файлы хранятся непосредственно в информационной базе. Для этого извлечем данные из реквизита типа ХранилищеЗначения и приведем их к объекту Картинка или ДвоичныеДанные.

Посмотрим на пример кода серверной процедуры выгрузки:


Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    
    ДвоичныеДанныеИлиКартинка = Выборка.Ссылка.ФайлКартинки.ФайлХранилище.Получить();
    
    Если ДвоичныеДанныеИлиКартинка = Неопределено Тогда
        Продолжить;
    КонецЕсли;
    
    ИмяФайла = "C:\ExportImage\" + Строка(Выборка.Ссылка.УникальныйИдентификатор()) + ".jpg";
    
    // Передаем извлеченные данные в конструктор объекта Картинка
    КартинкаВыгрузки = Новый Картинка(ДвоичныеДанныеИлиКартинка);
    КартинкаВыгрузки.Записать(ИмяФайла);
    
КонецЦикла;

Если в хранилище заведомо содержатся бинарные данные, выгрузку можно выполнить напрямую через объект ДвоичныеДанные без создания конструктора Новый Картинка():


ДанныеФайла = Хранилище.Получить();
Если ТипЗнч(ДанныеФайла) = Тип("ДвоичныеДанные") Тогда
    ДанныеФайла.Записать(ПутьКФайлу);
ИначеЕсли ТипЗнч(ДанныеФайла) = Тип("Картинка") Тогда
    ДанныеФайла.Записать(ПутьКФайлу);
КонецЕсли;

Способ 2. Рекомендуемый метод для типовых конфигураций (БСП)

Разберем универсальный способ, подходящий для типовых решений (УТ 11, КА, ERP, Комплексная автоматизация). В конфигурациях на базе БСП (Библиотеки Стандартных Подсистем) файлы номенклатуры могут храниться не только в базе данных, но и во внешних томах на сервере. При вынесенных томах реквизит ФайлХранилище будет пустым, и прямой способ работать не будет.

Рассмотрим использование штатной функции подсистемы РаботаСФайлами:


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

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

Важные правила и ограничения при работе с файлами

  1. Контекст выполнения (Сервер/Клиент): Помните, что метод .Записать() при вызове на сервере сохраняет файл в локальную файловую систему сервера 1С (или в доступную серверу сетевую папку). На стороне клиента запись этим методом не произойдет.
  2. Передача на клиент: Если необходимо выгрузить файл на локальный компьютер пользователя, используйте функцию ПоместитьВоВременноеХранилище на сервере и методы работы с файлами (ПолучитьФайлССервера) на клиенте.
  3. Оптимизация производительности: Не обращайтесь к реквизитам через точку в цикле (надобность вида Выборка.Ссылка.ФайлКартинки.ФайлХранилище порождает неявные запросы к базе). Обязательно получайте все нужные реквизиты прикрепленных файлов в исходном запросе выборки.
← На главную