Сохраняем изображение из вложений 1С: вручную, кодом, через COM и HTTP
Содержание
Получить картинку из присоединенных файлов 1С проще всего без кода: откройте карточку объекта, нажмите на скрепку «Присоединенные файлы», выделите изображение и выполните команду «Сохранить как». Программно то же самое делает одна строка на БСП: РаботаСФайлами.ДвоичныеДанныеФайла(Ссылка), а дальше ДвоичныеДанные.Записать(ПутьКФайлу).
Частое заблуждение — искать картинку в самом элементе справочника. Его там нет. В типовых конфигурациях 8.3 файл лежит отдельно: либо в служебной таблице информационной базы, либо на диске сервера в томах хранения. Элемент «Номенклатура» хранит только ссылку на запись присоединенного файла.
Где 1С хранит присоединенные файлы и картинки
Почти все типовые конфигурации на 8.3 (Бухгалтерия 3.0, ЗУП 3.1, УТ 11, КА, ERP) используют подсистему «Работа с файлами» из Библиотеки стандартных подсистем (БСП). Устроена она одинаково.
📁 Карточка файла. Для каждого владельца есть свой справочник присоединенных файлов. Имя строится по шаблону <Владелец>ПрисоединенныеФайлы: например, НоменклатураПрисоединенныеФайлы, КонтрагентыПрисоединенныеФайлы. В карточке — имя, расширение, размер, автор, ссылка на владельца (ВладелецФайла).
💾 Двоичные данные. Сами байты картинки лежат не в карточке. Где именно — решает настройка базы:
| Способ хранения | Где байты | Что важно при извлечении |
|---|---|---|
| В информационной базе | Служебный регистр БСП внутри базы | Попадает в выгрузку .dt, растёт размер базы |
| В томах на диске | Каталог на сервере или сетевой папке | Нужен доступ к тому; файл может «потеряться», если том перенесли |
Режим включают в разделе Администрирование → Общие настройки, блок про присоединенные файлы. Там же настраивают тома хранения.
🖼 Отдельные картинки в реквизитах. В старых и самописных конфигурациях изображение часто хранят прямо в реквизите типа ХранилищеЗначения. Это не присоединенный файл, и достают его иначе — об этом ниже.
Не читайте таблицы БСП напрямую запросом. Структура служебных регистров меняется между версиями библиотеки. Программный интерфейс РаботаСФайлами сам разберётся, где лежат байты — в базе или в томе.
Какой способ извлечения выбрать
| Способ | Когда подходит | Ограничения |
|---|---|---|
| Вручную «Сохранить как» | 1–10 картинок | Только руками |
| Код на БСП | Доработка формы, кнопка «Выгрузить фото» | Нужен доступ к конфигурации или расширение |
| Внешняя обработка | Разовая выгрузка всего каталога | Пишет файлы на сервере 1С |
| COM-соединение | Скрипт на Windows забирает файлы по расписанию | Лицензия на сеанс, разрядность comcntr.dll |
| HTTP-сервис | Сайт, приложение, интеграция | Нужен веб-сервер и публикация |
Как сохранить картинку из вложений вручную
Если нужно одно-два изображения, программировать не нужно.
- Откройте карточку объекта: товара, контрагента, документа.
- В командной панели найдите кнопку со скрепкой — «Присоединенные файлы». У номенклатуры в БП и УТ к файлам ведёт и область картинки в карточке.
- В списке файлов выделите нужный — по расширению
jpg,png,gif,bmp. - Выполните «Сохранить как» (команда есть в контекстном меню и в меню
Ещё). - Укажите папку на своём компьютере.
Альтернатива — «Открыть». Файл откроется в программе просмотра Windows, оттуда его тоже можно сохранить. Но 1С сначала положит копию в рабочий каталог пользователя, и при повторных открытиях там копится мусор.
⚠️ Если команда неактивна, проверьте права. Для просмотра присоединенных файлов нужен доступ к владельцу: нет прав на документ — нет доступа и к его вложениям.
Получение картинки из присоединенного файла кодом: ДвоичныеДанные и БСП
Для программиста главный инструмент — общий модуль РаботаСФайлами. Он работает на сервере.
Получить двоичные данные и записать на диск
&НаСервере
Процедура СохранитьКартинкуНаСервере(ПрисоединенныйФайл, Каталог)
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(ПрисоединенныйФайл, Ложь);
Если ДвоичныеДанные = Неопределено Тогда
Сообщить("Нет данных файла: " + Строка(ПрисоединенныйФайл));
Возврат;
КонецЕсли;
Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ПрисоединенныйФайл,
"Наименование, Расширение");
ИмяФайла = Реквизиты.Наименование + "." + Реквизиты.Расширение;
ДвоичныеДанные.Записать(Каталог + ПолучитьРазделительПути() + ИмяФайла);
КонецПроцедуры
Второй параметр Ложь говорит: не бросать исключение, если данных нет, а вернуть Неопределено. Для массовых обработок это удобнее — одна битая запись не остановит выгрузку.
Код выполняется на сервере, и путь Каталог — это путь на сервере 1С, а не на компьютере пользователя. В файловой базе это одно и то же. В клиент-серверной — нет.
Отдать картинку пользователю на клиент
Чтобы файл сохранился у пользователя, байты передают через временное хранилище. В БСП для этого есть готовая пара:
&НаСервере
Функция ДанныеФайлаНаСервере(ПрисоединенныйФайл)
Возврат РаботаСФайлами.ДанныеФайла(ПрисоединенныйФайл, УникальныйИдентификатор);
КонецФункции
&НаКлиенте
Процедура СохранитьКартинку(Команда)
ДанныеФайла = ДанныеФайлаНаСервере(Объект.ФайлКартинки);
РаботаСФайламиКлиент.СохранитьФайлКак(ДанныеФайла);
КонецПроцедуры
ДанныеФайла возвращает структуру. В ней есть адрес двоичных данных во временном хранилище, имя и расширение. СохранитьФайлКак сам покажет диалог выбора папки.
Показать картинку на форме
Если нужно не сохранить, а вывести изображение в поле картинки формы, сохранять на диск не нужно. Положите двоичные данные во временное хранилище и укажите адрес как значение реквизита формы, связанного с полем картинки:
АдресКартинки = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
Извлечение изображения из 1С через COM-соединение
COM нужен, когда картинки забирает внешняя программа на Windows: скрипт, сайт-синхронизатор, утилита склада. Внешняя программа подключается к базе как пользователь 1С и вызывает её код.
Что подготовить
- 🔧 Зарегистрировать компоненту
comcntr.dllтой же разрядности, что и вызывающая программа. Команда от имени администратора:
regsvr32 "C:\Program Files\1cv8\8.3.25.1374\bin\comcntr.dll"
Номер версии в пути замените на свой.
- 🔧 Создать в конфигурации (лучше в расширении) общий модуль с флагами «Сервер» и «Внешнее соединение».
- 🔧 Завести отдельного пользователя 1С с правами только на чтение нужных справочников.
Функция в общем модуле
Двоичные данные через COM передавать неудобно. Надёжнее вернуть строку Base64 и раскодировать её на стороне программы:
Функция КартинкаBase64(ИдентификаторФайла) Экспорт
Ссылка = Справочники.НоменклатураПрисоединенныеФайлы.ПолучитьСсылку(
Новый УникальныйИдентификатор(ИдентификаторФайла));
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(Ссылка, Ложь);
Если ДвоичныеДанные = Неопределено Тогда
Возврат "";
КонецЕсли;
Возврат Base64Строка(ДвоичныеДанные);
КонецФункции
Вызов из Python
import base64
import win32com.client
connector = win32com.client.Dispatch("V83.COMConnector")
conn = connector.Connect('File="C:\\Bases\\Trade";Usr="Export";Pwd="secret"')
module = getattr(conn, "ВыгрузкаКартинок")
data = getattr(module, "КартинкаBase64")("8f3c2a1e-5b7d-11ee-9c1a-00155d012345")
if data:
with open("C:\\Export\\item.jpg", "wb") as f:
f.write(base64.b64decode(data))
Для клиент-серверной базы строка подключения другая: Srvr="server1c";Ref="trade";. Base64 увеличивает объём примерно на треть. Для картинок каталога по 200–500 КБ это не критично. Для тысяч файлов по 10 МБ выгодней писать файлы на сервере и забирать папку.
Каждое COM-подключение занимает лицензию и стартует сеанс. Не открывайте соединение на каждую картинку — подключитесь один раз и обработайте весь список.
Картинки в хранилище значения и OLE-объектах
Сюда относятся два случая, которые с подсистемой файлов БСП не связаны.
Реквизит типа ХранилищеЗначения
В самописных базах и старых доработках картинку кладут в реквизит справочника. Извлекается она методом Получить(). Внутри может оказаться Картинка или ДвоичныеДанные — проверяйте тип:
Значение = СсылкаНаТовар.ФотоТовара.Получить();
Если ТипЗнч(Значение) = Тип("Картинка") Тогда
ДвоичныеДанные = Значение.ПолучитьДвоичныеДанные();
ИначеЕсли ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда
ДвоичныеДанные = Значение;
Иначе
ДвоичныеДанные = Неопределено;
КонецЕсли;
Если ДвоичныеДанные <> Неопределено Тогда
ДвоичныеДанные.Записать("C:\Export\" + СсылкаНаТовар.Код + ".png");
КонецЕсли;
Имя реквизита ФотоТовара здесь условное — посмотрите своё в конфигураторе. Расширение у такой картинки неизвестно. Формат можно узнать через Картинка.Формат(), либо по первым байтам файла: PNG начинается с 89 50 4E 47, JPEG — с FF D8 FF.
Картинка внутри вложенного документа Word или Excel
Бывает, что изображение прикреплено не отдельным файлом, а вставлено в документ .docx или .xlsx. Тогда:
- Сохраните вложение на диск обычным способом.
- Смените расширение на
.zip— современные форматы Office являются архивами. - Откройте архив. Картинки лежат в папке
word/mediaдля Word иxl/mediaдля Excel.
Так изображения выходят в исходном качестве, без пережатия, которое бывает при копировании из Word.
Старые форматы .doc и .xls архивами не являются. Их проще открыть в Office и сохранить в новом формате.
Массовая выгрузка изображений из 1С внешней обработкой
Типовая задача — выгрузить все фото номенклатуры для сайта или маркетплейса. Делается внешней обработкой с одной серверной процедурой.
Пример выгрузки фото всех товаров
&НаСервере
Процедура ВыгрузитьНаСервере(Каталог)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Файлы.Ссылка КАК Ссылка,
| Файлы.Расширение КАК Расширение,
| Файлы.ВладелецФайла.Код КАК КодТовара
|ИЗ
| Справочник.НоменклатураПрисоединенныеФайлы КАК Файлы
|ГДЕ
| НЕ Файлы.ПометкаУдаления
| И Файлы.Расширение В (&Расширения)
|УПОРЯДОЧИТЬ ПО
| КодТовара";
Расширения = Новый Массив;
Расширения.Добавить("jpg");
Расширения.Добавить("jpeg");
Расширения.Добавить("png");
Запрос.УстановитьПараметр("Расширения", Расширения);
Выборка = Запрос.Выполнить().Выбрать();
ПредыдущийКод = "";
Номер = 0;
Пока Выборка.Следующий() Цикл
КодТовара = СокрЛП(Выборка.КодТовара);
Номер = ?(КодТовара = ПредыдущийКод, Номер + 1, 1);
ПредыдущийКод = КодТовара;
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(Выборка.Ссылка, Ложь);
Если ДвоичныеДанные = Неопределено Тогда
Продолжить;
КонецЕсли;
ИмяФайла = СтрШаблон("%1_%2.%3", КодТовара,
Формат(Номер, "ЧГ=0"), НРег(Выборка.Расширение));
ДвоичныеДанные.Записать(Каталог + ПолучитьРазделительПути() + ИмяФайла);
КонецЦикла;
КонецПроцедуры
У товара с кодом 00-00000123 и тремя фото получатся файлы 00-00000123_1.jpg, 00-00000123_2.jpg, 00-00000123_3.jpg.
Что учесть
- 📌 Имя файла стройте из кода или артикула, а не из наименования. В наименованиях бывают
/,",*, на которыхЗаписать()упадёт. - 📌 Регистр расширения в базе бывает разный:
JPGиjpg. Если фильтр в запросе не сработал, приведите расширения к одному виду или добавьте оба варианта в массив. - 📌 Нужна только основная картинка товара? У номенклатуры в БП и УТ есть реквизит со ссылкой на основное изображение. Соберите запрос по нему, а не по всем файлам.
- 📌 На 20–30 тысяч файлов выгрузка идёт долго. Запускайте её фоновым заданием, а не в форме — иначе клиент «повиснет» на всё время работы.
Доступ к картинкам 1С по ссылке через HTTP-сервис
HTTP-сервис нужен, когда изображения должен получать сайт, мобильное приложение или чужая система — без COM и без Windows на той стороне.
Как собрать сервис
- В конфигураторе в расширении добавьте объект «HTTP-сервис», корневой URL —
images. - Добавьте шаблон URL
/file/{uid}и методGET. - Опубликуйте базу на веб-сервере (IIS или Apache) с флажком публикации HTTP-сервисов.
- Проверьте адрес вида
http://server/trade/hs/images/file/<идентификатор>.
Обработчик метода GET
Функция ФайлGET(Запрос)
Попытка
Идентификатор = Новый УникальныйИдентификатор(Запрос.ПараметрыURL["uid"]);
Исключение
Возврат Новый HTTPСервисОтвет(400);
КонецПопытки;
Ссылка = Справочники.НоменклатураПрисоединенныеФайлы.ПолучитьСсылку(Идентификатор);
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(Ссылка, Ложь);
Если ДвоичныеДанные = Неопределено Тогда
Возврат Новый HTTPСервисОтвет(404);
КонецЕсли;
Расширение = НРег(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Расширение"));
ТипКонтента = ?(Расширение = "png", "image/png", "image/jpeg");
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", ТипКонтента);
Ответ.Заголовки.Вставить("Cache-Control", "max-age=86400");
Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные);
Возврат Ответ;
КонецФункции
Сервис работает от имени пользователя 1С, который указан в публикации или передан в заголовке авторизации. Дайте ему минимальные права. Открывать доступ к базе без авторизации ради картинок не стоит: через тот же веб-сервер станут доступны и другие опубликованные сервисы.
Заголовок Cache-Control разгружает сервер 1С. Браузер и прокси не будут запрашивать одну и ту же картинку при каждом показе страницы.
Ошибки при извлечении картинок и что с ними делать
Частые вопросы
Можно ли получить картинку из 1С без прав администратора?
Сохранятся ли присоединенные файлы в выгрузке .dt?
Почему картинка в 1С выглядит меньше оригинала?
Как узнать уникальный идентификатор файла для HTTP-запроса?
Ссылка.УникальныйИдентификатор(). Внешняя система обычно получает его из той же выгрузки, где передаётся список товаров.