При разработке обработок выгрузки каталогов номенклатуры в «1С:Управление торговлей 11» или других конфигурациях на управляемых формах часто возникает задача выгрузить прикрепленные файлы изображений на диск. Рассмотрим, как правильно извлечь данные изображения из базы данных и записать их в файл, а также разберем причины возникающих ошибок.
Выясним причину популярной ошибки, с которой сталкиваются разработчики при попытке выгрузить файл. Ошибка возникает в случае, если реквизит хранилища (например, ФайлХранилище) считывается некорректно или возвращает не сам объект бинарных данных, а значение Undefined (Неопределено) или вложенное ХранилищеЗначения.
Если хранилище содержит сам объект типа Картинка, то прямой вызов метода .Получить().Записать() вызовет ошибку, так как из хранилища извлекается не объект ДвоичныеДанные, а внутреннее представление или неопределенное значение (например, если файлы хранятся во внешних томах на сервере).
Проанализируем базовый вариант выгрузки, когда файлы хранятся непосредственно в информационной базе. Для этого извлечем данные из реквизита типа ХранилищеЗначения и приведем их к объекту Картинка или ДвоичныеДанные.
Посмотрим на пример кода серверной процедуры выгрузки:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДвоичныеДанныеИлиКартинка = Выборка.Ссылка.ФайлКартинки.ФайлХранилище.Получить();
Если ДвоичныеДанныеИлиКартинка = Неопределено Тогда
Продолжить;
КонецЕсли;
ИмяФайла = "C:\ExportImage\" + Строка(Выборка.Ссылка.УникальныйИдентификатор()) + ".jpg";
// Передаем извлеченные данные в конструктор объекта Картинка
КартинкаВыгрузки = Новый Картинка(ДвоичныеДанныеИлиКартинка);
КартинкаВыгрузки.Записать(ИмяФайла);
КонецЦикла;
Если в хранилище заведомо содержатся бинарные данные, выгрузку можно выполнить напрямую через объект ДвоичныеДанные без создания конструктора Новый Картинка():
ДанныеФайла = Хранилище.Получить();
Если ТипЗнч(ДанныеФайла) = Тип("ДвоичныеДанные") Тогда
ДанныеФайла.Записать(ПутьКФайлу);
ИначеЕсли ТипЗнч(ДанныеФайла) = Тип("Картинка") Тогда
ДанныеФайла.Записать(ПутьКФайлу);
КонецЕсли;
Разберем универсальный способ, подходящий для типовых решений (УТ 11, КА, ERP, Комплексная автоматизация). В конфигурациях на базе БСП (Библиотеки Стандартных Подсистем) файлы номенклатуры могут храниться не только в базе данных, но и во внешних томах на сервере. При вынесенных томах реквизит ФайлХранилище будет пустым, и прямой способ работать не будет.
Рассмотрим использование штатной функции подсистемы РаботаСФайлами:
// СсылкаНаПрисоединенныйФайл — ссылка на справочник НоменклатураПрикрепленныеФайлы
СсылкаНаФайл = Выборка.ФайлКартинки;
Если ЗначениеЗаполнено(СсылкаНаФайл) Тогда
// Метод БСП сам определяет, где лежит файл (в базе или в томе на диске)
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл);
Если ДвоичныеДанные <> Неопределено Тогда
// Формируем путь с учетом расширения файла из справочника
ПолноеИмяФайла = ПапкаВыгрузки + СсылкаНаФайл.Наименование + "." + СсылкаНаФайл.Расширение;
ДвоичныеДанные.Записать(ПолноеИмяФайла);
КонецЕсли;
КонецЕсли;
.Записать() при вызове на сервере сохраняет файл в локальную файловую систему сервера 1С (или в доступную серверу сетевую папку). На стороне клиента запись этим методом не произойдет.ПоместитьВоВременноеХранилище на сервере и методы работы с файлами (ПолучитьФайлССервера) на клиенте.Выборка.Ссылка.ФайлКартинки.ФайлХранилище порождает неявные запросы к базе). Обязательно получайте все нужные реквизиты прикрепленных файлов в исходном запросе выборки.