Разработка и Конфигурация · 14 мин
Как получить картинку из присоединённых файлов в 1С
Как получить картинку из присоединённых файлов 1С: работа с хранилищем значений, методы Получить() и ПолучитьИзВременногоХранилища, примеры кода и типичные ошибки.
Присоединённые файлы в типовых конфигурациях 1С (справочники НоменклатураПрисоединенныеФайлы, Файлы, ХранилищеФайлов и подобные) хранят картинки товаров, подписи, логотипы и сканы документов. Задача «получить картинку» возникает при выводе изображения на форму, в печатный макет, при обмене с сайтом или при выгрузке данных на диск.
Способ извлечения зависит от того, как устроено хранение в конкретной конфигурации. В большинстве типовых решений на базе библиотеки стандартных подсистем (БСП) двоичные данные файла лежат в регистре сведений ДвоичныеДанныеФайлов или напрямую в реквизите типа ХранилищеЗначения. В самописных конфигурациях файл может храниться в реквизите объекта, в томах на диске или во внешней системе.
Ниже разобраны основные сценарии: извлечение картинки кодом встроенного языка, вывод её на форму и в печатную форму, сохранение на диск, а также типичные ошибки — пустая картинка, неправильный формат, потеря данных при переносе.
Где 1С хранит картинки присоединённых файлов
Перед написанием кода нужно понять, где физически лежит картинка. В конфигурациях на основе БСП (Управление торговлей, ERP, Бухгалтерия предприятия, Зарплата и управление персоналом) применяется двухуровневая модель: в справочнике присоединённых файлов хранятся метаданные (имя, расширение, размер, владелец), а сами двоичные данные — в регистре сведений ДвоичныеДанныеФайлов или в томах на диске, если включено хранение в томах.
В простых и самописных конфигурациях картинка часто лежит прямо в реквизите объекта с типом ХранилищеЗначения — например, в реквизите ДанныеКартинки справочника товаров. В этом случае данные извлекаются напрямую методом Получить() без промежуточных регистров.
Узнать структуру хранения можно через конфигуратор: откройте справочник присоединённых файлов, посмотрите состав реквизитов и связанные регистры сведений. Также полезно проверить константу ХранитьФайлыВТомахНаДиске — если она установлена, двоичных данных в базе не будет, и код должен читать файл с диска.
Данные извлекаются запросом к регистру сведений
Достаточно метода Получить() у реквизита
Нужно читать файл по пути из тома
Получение картинки из хранилища значения
Самый простой случай — картинка в реквизите типа ХранилищеЗначения. Метод Получить() возвращает двоичные данные, из которых конструируется объект Картинка:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.ДанныеКартинки КАК ДанныеКартинки
|ИЗ
| Справочник.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ТоварСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ДвоичныеДанные = Выборка.ДанныеКартинки.Получить();
Если ДвоичныеДанные <> Неопределено Тогда
Картинка = Новый Картинка(ДвоичныеДанные);
КонецЕсли;
КонецЕсли;
Ключевой момент — обязательная проверка на Неопределено. Если в реквизите пустое хранилище, Получить() вернёт Неопределено, и конструктор Новый Картинка() вызовет исключение, которое прервёт выполнение кода. Это самая частая причина падения обработок при массовой выгрузке картинок.
Объект Картинка подходит для вывода в табличный документ и печатные формы. Если картинку нужно показать на управляемой форме, двоичные данные обычно помещают во временное хранилище, а в реквизит формы записывают адрес хранилища — об этом ниже.
Извлечение файла из подсистемы работы с файлами БСП
В типовых конфигурациях не следует обращаться к регистру ДвоичныеДанныеФайлов напрямую: структура хранения может меняться между версиями библиотеки, а при хранении в томах данных в регистре вообще нет. Правильный путь — программный интерфейс подсистемы:
// ПрисоединенныйФайл — ссылка на элемент справочника
// НоменклатураПрисоединенныеФайлы (или аналогичный)
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(ПрисоединенныйФайл);
Если ДвоичныеДанные <> Неопределено Тогда
Картинка = Новый Картинка(ДвоичныеДанные);
КонецЕсли;
Функция сама учитывает, где лежит файл — в базе или в томе на диске — и возвращает двоичные данные в едином виде. На клиенте вместо неё используют асинхронные методы получения файла из хранилища, поскольку прямой вызов серверных функций из клиентского контекста ограничен.
Чтобы найти нужный присоединённый файл, запросите справочник присоединённых файлов по владельцу. У владельца может быть несколько файлов, поэтому фильтруйте по расширению (jpg, png, bmp) или по признаку основного изображения, если он предусмотрен конфигурацией.
- 1Найдите ссылку на присоединённый файл запросом по владельцу и расширению
- 2Вызовите РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл)
- 3Проверьте результат на Неопределено
- 4Создайте объект Картинка из двоичных данных или поместите данные во временное хранилище
- 5Выведите картинку на форму, в макет или сохраните на диск
Вывод картинки на управляемую форму
На управляемой форме элемент «Поле картинки» работает через адрес временного хранилища, а не через объект Картинка напрямую. Типовой приём выглядит так:
&НаСервере
Процедура ЗагрузитьКартинку(ПрисоединенныйФайл)
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(ПрисоединенныйФайл);
Если ДвоичныеДанные = Неопределено Тогда
АдресКартинки = "";
Возврат;
КонецЕсли;
// АдресКартинки — строковый реквизит формы
АдресКартинки = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
КонецПроцедуры
Второй параметр ПоместитьВоВременноеХранилище — уникальный идентификатор формы — привязывает данные к времени жизни формы. Без него хранилище очистится после завершения серверного вызова, и поле картинки останется пустым. Это вторая по частоте ошибка при выводе изображений на форму.
У поля формы, отображающего картинку, проверьте свойства: ПутьКДанным должен указывать на строковый реквизит с адресом, а РазмерКартинки обычно ставят в «Пропорционально», чтобы изображение не искажалось. Если картинка не отображается, первым делом проверьте, не пуст ли адрес в реквизите после серверного вызова.
Вставка картинки в печатную форму и макет
В табличный документ картинка вставляется через коллекцию рисунков области. Сначала в макете создают область с именем, затем программно добавляют рисунок:
ТабДок = Новый ТабличныйДокумент;
Область = Макет.ПолучитьОбласть("Шапка");
ТабДок.Вывести(Область);
Если Картинка <> Неопределено Тогда
Рисунок = ТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
Рисунок.Картинка = Картинка;
Рисунок.Разместить(ТабДок.Область("R1C1"));
Рисунок.Высота = 20;
Рисунок.Ширина = 20;
КонецЕсли;
Обратите внимание: размеры рисунка задаются в миллиметрах, и если их не ограничить, большая фотография товара «разорвёт» макет. Для печатных форм с изображениями разной ширины и высоты полезно вычислять пропорции, опираясь на реальный размер картинки в пикселях — свойства Картинка.Ширина() и Картинка.Высота() доступны в новых версиях платформы.
Если картинка нужна в макете постоянно (например, логотип организации), иногда проще вставить её непосредственно в макет конфигурации, а не извлекать из присоединённых файлов при каждой печати. Это ускоряет формирование документа, но требует обновления макета при смене логотипа.
Сохранение картинки на диск и выгрузка пакетом
Для сохранения извлечённой картинки в файл достаточно метода Записать() двоичных данных:
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(ПрисоединенныйФайл);
Если ДвоичныеДанные <> Неопределено Тогда
ДвоичныеДанные.Записать("D:\Выгрузка\Фото_" + КодТовара + ".jpg");
КонецЕсли;
При пакетной выгрузке (например, всех фото номенклатуры для сайта) соблюдайте два правила. Во-первых, получайте список присоединённых файлов одним запросом, а не перебором объектов — это сокращает число обращений к базе на порядки. Во-вторых, формируйте имена файлов из безопасных символов: в артикулах и наименованиях встречаются символы, недопустимые в именах файлов (слеши, двоеточия, кавычки).
Учитывайте расширение исходного файла: если сохранить PNG-картинку с расширением .jpg, файл откроется в большинстве просмотрщиков, но при передаче в строгие системы (некоторые маркетплейсы, EDI) такая подмена формата вызовет отказ загрузки. Расширение берите из реквизита Расширение присоединённого файла.
Особенности веб-клиента, тонкого клиента и мобильной платформы
В веб-клиенте прямая запись файла на диск пользователя невозможна без расширения работы с файлами. Картинку сначала передают на клиент через временное хранилище, затем предлагают пользователю сохранить через диалог либо показывают в браузере по адресу хранилища. Методы НачатьПолучениеФайлов и ПолучитьФайл работают асинхронно и требуют установки расширения в браузере.
В тонком клиенте действуют те же ограничения на синхронные вызовы, если в конфигурации отключён режим использования модальности. Пишите код получения файлов через описания оповещений, иначе обработка не запустится у части пользователей.
Если картинка нужна для передачи во внешнюю систему (HTTP-сервис, обмен с сайтом), двоичные данные обычно кодируют в Base64 функцией Base64Строка(). Помните, что кодирование увеличивает объём данных примерно на треть — для больших фотографий это существенно влияет на трафик и время обмена.
Как выбрать способ извлечения
Проверка результата и частые проблемы
После извлечения картинки убедитесь, что результат корректен: файл открывается в графическом редакторе, размер файла больше нуля, формат соответствует ожидаемому. Программно проверить валидность можно попыткой создать объект Картинка в попытке/исключении — повреждённые данные вызовут исключение, которое можно обработать и записать в журнал.
Характерная проблема при переносе данных между базами — «битые» ссылки присоединённых файлов: элемент справочника есть, а двоичных данных нет (например, регистр не включили в план обмена). Внешне это выглядит как пустые картинки без ошибок. Диагностируется проверкой результата ДвоичныеДанныеФайла() на Неопределено по выборке файлов.
Ещё одна ситуация — картинка извлекается, но выглядит искажённой или обрезанной. Обычно причина не в извлечении, а в отображении: проверьте свойства размера у поля формы или рисунка табличного документа. Сами двоичные данные при штатном хранении не меняются.
Как проверить результат
Больше нуля, сопоставим с исходным файлом
Ноль или Неопределено — данные не извлечены
Объект создан без исключения
Исключение — данные повреждены или формат не поддерживается
Изображение видно, пропорции сохранены
Пустое поле — проверьте адрес хранилища и ПутьКДанным
Открывается в просмотрщике, корректное расширение
Не открывается — неверное расширение или усечённые данные
Частые вопросы
Почему Получить() возвращает Неопределено, хотя картинка видна в карточке?
Скорее всего, вы обращаетесь не к тому реквизиту или не к тому объекту. В типовых конфигурациях картинка в карточке показывается из присоединённого файла, а реквизит объекта может быть пустым. Найдите присоединённый файл по владельцу и извлекайте данные через подсистему работы с файлами.
Как получить картинку, если файлы хранятся в томах на диске?
Напрямую читать файлы с диска не нужно — функция РаботаСФайлами.ДвоичныеДанныеФайла() сама определяет место хранения и возвращает данные. Ручное чтение из тома оправдано только внешними средствами при недоступной базе.
Можно ли получить картинку без программирования?
Да: откройте присоединённый файл из карточки объекта и сохраните его через команду «Сохранить как» в форме файла. Также есть типовая команда выгрузки файлов в каталог в списке присоединённых файлов. Программный способ нужен для автоматизации и массовой выгрузки.
Какие форматы картинок поддерживает объект Картинка?
Платформа работает с распространёнными растровыми форматами — PNG, JPEG, BMP, GIF, TIFF, а также с векторным SVG в ограниченном объёме. Экзотические форматы (например, WebP в старых версиях платформы) могут не поддерживаться — такие файлы извлекайте как двоичные данные без создания объекта Картинка.
Почему при массовой выгрузке обработка работает очень медленно?
Основные причины: получение списка файлов по одному объекту вместо пакетного запроса, выгрузка в файловой базе с блокировками, запись на сетевой диск. Оптимизируйте запрос, перенесите операцию в фоновое задание и пишите файлы на локальный диск сервера.
Как передать картинку на сайт или в другую систему?
Стандартный способ — закодировать двоичные данные в Base64 функцией Base64Строка() и передать строкой в теле HTTP-запроса или XML/JSON-пакета. На принимающей стороне строка декодируется обратно в файл. Для больших объёмов предпочтительнее передача файлом через multipart-запрос.
Что важно запомнить
В типовых конфигурациях картинку извлекайте через РаботаСФайлами.ДвоичныеДанныеФайла(), в простых — методом Получить() из хранилища значения. Всегда проверяйте результат на Неопределено, для формы используйте временное хранилище с идентификатором формы, а массовую выгрузку выполняйте пакетным запросом в фоновом задании.