Разработка и Конфигурация · 11 мин
Как получить картинку из хранилища значений 1С
Как извлечь картинку из хранилища значений в 1С: метод Получить(), работа с двоичными данными, вывод на форму и в табличный документ, типичные ошибки.
В типовых и самописных конфигурациях 1С изображения — фотографии товаров, сканы документов, логотипы, подписи — чаще всего хранятся в реквизитах с типом «ХранилищеЗначения». Внутри такого реквизита лежат не сами данные, а сериализованный объект, поэтому обратиться к картинке напрямую, как к строке или числу, нельзя: значение нужно сначала извлечь методом Получить().
Типичная задача выглядит так: в справочнике «Номенклатура» есть реквизит «ФайлКартинки» типа «ХранилищеЗначения», и нужно показать изображение на форме, вывести в печатную форму или сохранить на диск. Во всех сценариях первый шаг одинаков — вызвать Хранилище.Получить(), который вернёт либо объект типа «Картинка», либо «ДвоичныеДанные», либо Неопределено, если реквизит пуст.
Дальнейшие действия зависят от того, что именно лежит в хранилище и куда нужно вывести результат. Ниже разобраны основные сценарии: вывод на управляемую форму, вставка в табличный документ, сохранение в файл, а также проверки, которые защищают код от ошибок на пустых или повреждённых данных.
Что такое хранилище значений и почему картинку нельзя прочитать напрямую
«ХранилищеЗначения» — это специальный тип данных 1С, предназначенный для сохранения в базе произвольных объектов: картинок, двоичных данных, файлов, сериализованных структур. В базе данных содержимое хранится в сжатом виде, и платформа не знает заранее, какого типа объект внутри.
Поэтому при чтении реквизита вы получаете объект-обёртку. Чтобы добраться до содержимого, используется метод Получить(). Обратная операция — запись — выполняется конструктором Новый ХранилищеЗначения(Данные), где Данные — это картинка, двоичные данные или другой сериализуемый объект.
Важно понимать: то, что вернёт Получить(), зависит от того, что положили при записи. Если сохраняли объект «Картинка» — вернётся «Картинка», если «ДвоичныеДанные» — вернутся двоичные данные, и код должен уметь работать с обоими вариантами.
Базовое извлечение: метод Получить() и проверка результата
Минимальный безопасный код извлечения выглядит так:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Номенклатура.ФайлКартинки КАК ФайлКартинки
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", ТоварСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ДанныеКартинки = Выборка.ФайлКартинки.Получить();
Если ДанныеКартинки = Неопределено Тогда
// картинки нет — показываем заглушку или пропускаем
КонецЕсли;
КонецЕсли;
Обратите внимание: запросом выбирается сам реквизит хранилища, а Получить() вызывается уже в коде. Это стандартный и самый управляемый способ. Извлекать хранилище «в лоб» через точку от ссылки (ТоварСсылка.ФайлКартинки.Получить()) тоже можно, но при обходе большого списка товаров это порождает отдельное обращение к базе на каждый элемент — на больших объёмах такой подход заметно медленнее одного запроса.
Проверка на Неопределено обязательна: пустое хранилище — нормальная ситуация, и обращение к методам результата без проверки приведёт к ошибке «Значение не является значением объектного типа».
Вывод картинки на управляемую форму
На управляемой форме нельзя напрямую присвоить картинку элементу формы — используется механизм временного хранилища. В форму добавляется реквизит типа «Строка» (например, «АдресКартинки»), элемент формы типа «Поле картинки» связывается с этим реквизитом, а в коде адрес заполняется так:
ДанныеКартинки = ТоварОбъект.ФайлКартинки.Получить();
Если ДанныеКартинки = Неопределено Тогда
АдресКартинки = "";
Иначе
Если ТипЗнч(ДанныеКартинки) = Тип("Картинка") Тогда
ДвоичныеДанные = ДанныеКартинки.ПолучитьДвоичныеДанные();
Иначе
ДвоичныеДанные = ДанныеКартинки;
КонецЕсли;
АдресКартинки = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
КонецЕсли;
Ключевой момент — второй параметр ПоместитьВоВременноеХранилище. Если передать УникальныйИдентификатор формы, данные будут жить, пока открыта форма, и адрес останется валидным при серверных вызовах. Без этого параметра адрес может стать недействительным после очередного обращения к серверу, и картинка «пропадёт».
Если картинка обновляется (пользователь выбрал другой товар), прежний адрес желательно освободить через УдалитьИзВременногоХранилища(АдресКартинки), чтобы не копить данные в памяти сеанса.
- 1Добавьте в форму реквизит типа Строка и элемент Поле картинки, связанный с ним
- 2Извлеките значение из хранилища методом Получить() и проверьте на Неопределено
- 3Приведите результат к двоичным данным (для Картинка — через ПолучитьДвоичныеДанные())
- 4Поместите данные во временное хранилище с УникальныйИдентификатор формы
- 5Присвойте полученный адрес реквизиту формы и проверьте отображение
Сохранение картинки в файл на диск
Если цель — выгрузить изображение из базы, достаточно получить двоичные данные и записать их методом Записать():
ДанныеКартинки = ТоварСсылка.ФайлКартинки.Получить();
Если ДанныеКартинки <> Неопределено Тогда
Если ТипЗнч(ДанныеКартинки) = Тип("Картинка") Тогда
ДвоичныеДанные = ДанныеКартинки.ПолучитьДвоичныеДанные();
Иначе
ДвоичныеДанные = ДанныеКартинки;
КонецЕсли;
ДвоичныеДанные.Записать("C:\Temp\image.jpg");
КонецЕсли;
На тонком и веб-клиенте прямая запись на диск пользователя из серверного кода невозможна — используйте ПолучитьФайл() или передачу через временное хранилище с последующим сохранением на клиенте. Учитывайте также расширение файла: если в хранилище могли сохранить и PNG, и JPEG, расширение лучше хранить отдельным реквизитом, как это сделано в типовом механизме присоединенных файлов БСП.
Вывод картинки в табличный документ и печатную форму
Для макетов и печатных форм картинка вставляется в область табличного документа через коллекцию рисунков:
ДанныеКартинки = ТоварСсылка.ФайлКартинки.Получить();
Если ДанныеКартинки <> Неопределено Тогда
Если ТипЗнч(ДанныеКартинки) = Тип("ДвоичныеДанные") Тогда
Картинка = Новый Картинка(ДанныеКартинки);
Иначе
Картинка = ДанныеКартинки;
КонецЕсли;
Рисунок = ОбластьМакета.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
Рисунок.Картинка = Картинка;
Рисунок.РазмерПропорционально = Истина;
КонецЕсли;
Альтернативный вариант — заранее разместить в макете именованный рисунок и подставлять в него картинку по имени: ТабДок.Рисунки["ФотоТовара"].Картинка = Картинка;. Это удобнее, когда позиция и размер изображения фиксированы дизайном печатной формы.
Способы вывода картинки
Подходит для интерактивного просмотра. Ограничение: нужен реквизит-строка с адресом и управление временем жизни хранилища.
Подходит для печатных форм и отчётов. Ограничение: работает только в табличном документе, не на форме.
Подходит для выгрузки и обмена. Ограничение: на тонком/веб-клиенте требует передачи файла через сервер.
Типичные ошибки и как их избежать
Самая частая проблема — обращение к методам результата Получить() без проверки на Неопределено. Вторая по распространённости — несовпадение типов: код ожидает «Картинка», а в хранилище лежат «ДвоичныеДанные» (или наоборот), потому что разные процедуры записи сохраняли разное. Лечится единой функцией приведения результата к нужному типу.
Третья группа ошибок связана с временным хранилищем на форме: адрес создаётся без привязки к форме, и после серверного вызова картинка исчезает, либо старые адреса не удаляются и память сеанса растёт. Четвёртая — попытка получить хранилище через точку от ссылки в цикле по большой выборке, что резко увеличивает число обращений к СУБД.
Проверка результата и производительность
После внедрения кода проверьте три ситуации: товар с картинкой, товар без картинки и товар, где в хранилище записан «не тот» тип. Все три ветки должны отрабатывать без исключений, а пустой случай — показывать заглушку или пустое поле, а не ошибку.
По производительности действует простое правило: извлекайте хранилища только для тех строк, которые реально показываются. В списках с сотнями позиций картинки обычно подгружают по требованию (для текущей строки или видимой страницы), а не одним запросом с выборкой всех хранилищ — поля с двоичными данными тяжёлые, и их массовая выборка замедляет и запрос, и передачу по сети.
Как проверить результат
Картинка видна и сохраняется после серверных вызовов формы
Картинка появляется и исчезает или не показывается вовсе
Код отрабатывает без ошибки, показывается заглушка или пустое поле
Ошибка «Значение не является значением объектного типа»
Код корректно обрабатывает и Картинка, и ДвоичныеДанные
Исключение при несовпадении типа
Файл открывается графическим просмотрщиком без повреждений
Файл нулевого размера или не открывается
Часто задаваемые вопросы
Чем отличается Картинка от ДвоичныхДанных при извлечении из хранилища?
«Картинка» — объект платформы с методами обработки изображения (получение двоичных данных, преобразование формата). «ДвоичныеДанные» — просто байты файла без интерпретации. Для вывода на форму нужны двоичные данные, для рисунка табличного документа — объект «Картинка», который можно создать конструктором Новый Картинка(ДвоичныеДанные).
Почему Получить() возвращает Неопределено, хотя картинку загружали?
Чаще всего значение было записано в другой реквизит или в другой объект (например, в присоединенные файлы, а не в реквизит справочника). Также возможна ситуация, когда запись выполнялась в транзакции, которая откатилась. Проверьте, какой именно реквизит заполняет процедура загрузки в вашей конфигурации.
Можно ли получить картинку из хранилища запросом напрямую?
Запросом можно выбрать сам реквизит типа «ХранилищеЗначения», но извлечь содержимое внутри запроса нельзя — метод Получить() вызывается уже в коде после выборки. Функций языка запросов для распаковки хранилища не существует.
Как вывести картинки сразу для списка товаров, не замедлив форму?
Не выбирайте хранилища для всех строк списка. Обычно картинку подгружают только для текущей строки при её активизации или для видимой порции данных. Если нужны миниатюры в таблице, лучше заранее сформировать уменьшенные копии и хранить их отдельно — это снижает объём передаваемых данных.
Почему картинка на управляемой форме пропадает после нажатия кнопки?
Причина — адрес временного хранилища создан без привязки к форме. Передайте в ПоместитьВоВременноеХранилище вторым параметром УникальныйИдентификатор формы — тогда данные будут жить, пока форма открыта, и адрес останется действительным при серверных вызовах.
Как сохранить картинку из базы на компьютер пользователя в тонком клиенте?
Прямая запись на диск клиента из серверного кода невозможна. Поместите двоичные данные во временное хранилище на сервере, передайте адрес на клиент и сохраните файл методом ПолучитьФайл() или через диалог сохранения с использованием НачатьПолучениеФайлаССервера.
Что важно запомнить
Картинка из хранилища значений извлекается методом Получить() с обязательной проверкой на Неопределено и тип результата. Для формы используйте временное хранилище с привязкой к УникальныйИдентификатор, для печати — рисунок табличного документа, для выгрузки — запись двоичных данных в файл. Не выбирайте хранилища массово без необходимости.