Как программно выгрузить прикрепленные изображения номенклатуры на диск в 1С?

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

При разработке интеграций с интернет-магазинами, мобильными приложениями или внешними витринами часто возникает задача массовой или точечной выгрузки картинок товаров на диск сервера. Разработчики нередко пытаются получить двоичные данные напрямую из реквизита ФайлХранилище справочника присоединенных файлов, однако вызов метода Получить() возвращает Неопределено. Разберем по шагам, почему это происходит и какими способами можно корректно выгрузить файлы изображений.

Почему ФайлХранилище.Получить() возвращает Неопределено?

В современных конфигурациях на платформе «1С:Предприятие 8.3» (таких как «Управление торговлей», «ERP Управление предприятием», «Комплексная автоматизация», «Управление нашей фирмой», «Бухгалтерия предприятия» и др.) работа с файлами реализована на базе подсистемы «Присоединенные файлы» Библиотеки стандартных подсистем (БСП).

Проанализируем особенности архитектуры хранения файлов в БСП:

  1. Реквизит ФайлХранилище в справочниках вида НоменклатураПрисоединенныеФайлы является устаревшим и оставлен исключительно для обратной совместимости. Сами двоичные данные в нем не сохраняются.
  2. Если в настройках программы выбрано хранение файлов в информационной базе, двоичные данные помещаются в отдельный регистр сведений — ПрисоединенныеФайлы (или ДвоичныеДанныеФайлов в актуальных версиях БСП) в ресурс ХранимыйФайл.
  3. Если включено хранение файлов в томах на диске (справочник ТомаХраненияФайлов), то данные вообще не хранятся в таблицах СУБД: в справочнике заполняются реквизиты Том и ПутьКФайлу, а сам файл физически лежит в сетевой или локальной папке тома.

Способ 1. Универсальное получение файла через программный интерфейс БСП (рекомендуемый)

Штатный механизм БСП предоставляет готовый программный интерфейс, который автоматически проверяет способ хранения (в базе или в томе на диске), считывает двоичные данные и возвращает готовый объект ДвоичныеДанные. Это избавляет от необходимости писать сложные запросы и обрабатывать разные варианты размещения файлов вручную.

Рассмотрим пример функции выгрузки основного изображения номенклатуры на диск:


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

Способ 2. Прямое чтение из регистра сведений запросом

Если по каким-то причинам вызовы модулей БСП недоступны или файлы гарантированно хранятся только внутри информационной базы (без использования томов на диске), данные можно извлечь прямым запросом к регистру сведений ПрисоединенныеФайлы.

Посмотрим на пример реализации прямого запроса:


&НаСервере
Процедура ВыгрузитьКартинкиЗапросом(СсылкаНоменклатура, КаталогВыгрузки)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ПрисоединенныеФайлы.ХранимыйФайл КАК ХранимыйФайл,
        |   НоменклатураПрисоединенныеФайлы.Расширение КАК Расширение,
        |   Номенклатура.Код КАК Код
        |ИЗ
        |   Справочник.Номенклатура КАК Номенклатура
        |   ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.НоменклатураПрисоединенныеФайлы КАК НоменклатураПрисоединенныеФайлы
        |       ПО Номенклатура.ФайлКартинки = НоменклатураПрисоединенныеФайлы.Ссылка
        |   ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПрисоединенныеФайлы КАК ПрисоединенныеФайлы
        |       ПО ПрисоединенныеФайлы.ПрисоединенныйФайл = НоменклатураПрисоединенныеФайлы.Ссылка
        |ГДЕ
        |   Номенклатура.Ссылка = &Номенклатура";
    
    Запрос.УстановитьПараметр("Номенклатура", СсылкаНоменклатура);
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        
        Если Выборка.ХранимыйФайл <> Неопределено Тогда
            
            ДвоичныеДанные = Выборка.ХранимыйФайл.Получить();
            
            Если ТипЗнч(ДвоичныеДанные) = Тип("ДвоичныеДанные") Тогда
                ПолноеИмяФайла = КаталогВыгрузки + Выборка.Код + "." + Выборка.Расширение;
                ДвоичныеДанные.Записать(ПолноеИмяФайла);
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Важные технические нюансы при серверной выгрузке файлов

Выясним частые подводные камни, с которыми сталкиваются при сохранении файлов на диск:

  1. Права службы сервера: Код с директивой &НаСервере выполняется в контексте пользователя операционной системы, от имени которого запущена служба сервера 1С (например, usr1cv8). У этого системного пользователя обязательно должны быть права на запись в целевую директорию и права на чтение каталогов томов хранения.
  2. Формат расширения: В реквизите Расширение справочников присоединенных файлов значение обычно хранится без точки (например, jpg, png). При формировании имени результирующего файла точку необходимо добавлять вручную.
  3. Кроссплатформенность путей: Если сервер 1С работает под управлением Linux, использование путей формата Windows (например, C:\wamp64\...) приведет к ошибке. Для формирования путей рекомендуется использовать системный разделитель через ПолучитьРазделительПути().
  4. Оптимизация памяти: При массовой пакетной выгрузке сотен тысяч изображений получение больших двоичных данных в память может вызвать ее переполнение. Для таких задач следует реализовывать обработку порциями и освобождать неиспользуемые переменные.
← На главную