Как правильно получить присоединенный файл в 1С, если реквизит ФайлХранилище возвращает Неопределено

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

При работе с современными конфигурациями на платформе 1С:Предприятие 8.3, такими как Управление нашей фирмой (УНФ), ERP или Бухгалтерия предприятия 3.0, разработчики часто сталкиваются с ситуацией, когда прямое обращение к реквизитам справочников присоединенных файлов не дает ожидаемого результата. В этой статье мы подробно разберем, почему стандартный метод получения данных через ХранилищеЗначения.Получить() может возвращать Неопределено, даже если файл визуально присутствует в системе, и как правильно извлекать эти данные с помощью механизмов Библиотеки стандартных подсистем (БСП).

Почему прямое обращение к реквизиту ФайлХранилище не работает?

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

  1. Хранение в томах на диске. Если в настройках системы включено хранение файлов в томах (на сетевых дисках), данные в саму базу данных (в реквизит ФайлХранилище) не записываются. Вместо этого заполняются реквизиты Том и ПутьКФайлу.
  2. Версионность файлов. Часто данные хранятся не в основном элементе справочника присоединенных файлов, а в подчиненном справочнике ВерсииФайлов. Основной элемент лишь хранит ссылку на текущую активную версию.
  3. Оптимизация платформы. Для ускорения работы со списками и объектами платформа может не считывать тяжелые бинарные поля при обычном получении объекта.

Выясним причину на примере кода, который часто приводит к ошибке:


// Ошибочный подход для конфигураций на БСП
Выборка = Справочники.НоменклатураПрисоединенныеФайлы.Выбрать();
Пока Выборка.Следующий() Цикл
    // Возвращает Неопределено, если файл в томе или используется версионность
    Данные = Выборка.ФайлХранилище.Получить(); 
КонецЦикла;

Использование программного интерфейса БСП для получения файлов

Для корректной работы с файлами необходимо использовать функции общего модуля РаботаСФайлами. Этот модуль автоматически определяет, где именно хранится файл (в базе или в томе), проверяет права доступа пользователя и возвращает актуальные данные. Разберем наиболее эффективные способы решения задачи.

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


&НаКлиенте
Процедура ПрочитатьФайлВложения(СсылкаНаФайл)
    
    // Подготавливаем данные для открытия
    ДанныеФайла = РаботаСФайламиСлужебныйВызовСервера.ДанныеФайлаДляОткрытия(СсылкаНаФайл, Неопределено);
    
    // Получаем путь к временному файлу, который создала система
    ПолныйПуть = ДанныеФайла.ПолноеИмяФайлаВРабочемКаталоге;
    
    // Передаем путь на сервер для дальнейшей обработки данных
    ПрочитатьДанныеНаСервере(ПолныйПуть);
    
КонецПроцедуры

Обратите внимание, что метод ДанныеФайлаДляОткрытия возвращает структуру, содержащую не только путь, но и информацию о том, был ли файл изменен, заблокирован или требует ли он расшифровки. Это избавляет разработчика от необходимости вручную проверять настройки хранения в константах системы.

Загрузка данных файла в Табличный документ

Рассмотрим подробнее ситуацию, когда присоединенный файл является документом Excel или MXL, и нам нужно отобразить его содержимое в объекте ТабличныйДокумент на форме. После того как мы получили локальный путь к файлу, мы можем прочитать его на сервере:


&НаСервере
Процедура ПрочитатьДанныеНаСервере(ИмяФайла)
    
    // Создаем объект ТабличныйДокумент
    ТабДок = Новый ТабличныйДокумент;
    
    Попытка
        // Платформа 1С умеет определять формат (mxl, xlsx) по расширению файла
        ТабДок.Прочитать(ИмяФайла);
        
        // Выводим результат в реквизит формы типа "ТабличныйДокумент"
        НашТабличныйДокументНаФорме.Очистить();
        НашТабличныйДокументНаФорме.Вывести(ТабДок);
    Исключение
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось прочитать файл: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Альтернативный метод: получение двоичных данных в память

Если ваша задача не требует записи файла на диск пользователя, а подразумевает обработку данных "в памяти" (например, отправка по почте или парсинг текста), лучше использовать метод ДвоичныеДанныеФайла. Проанализируем, как это выглядит в коде:


&НаСервере
Функция ПолучитьБинарныеДанные(СсылкаФайла)
    
    // Универсальный способ получения данных через БСП
    ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаФайла);
    
    Если ДвоичныеДанные = Неопределено Тогда
        Возврат Ложь; // Файл не найден или нет доступа
    КонецЕсли;
    
    // Теперь с объектом типа ДвоичныеДанные можно работать
    // Например, создать из них поток или записать во временное хранилище
    АдресВХ = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
    
    Возврат АдресВХ;
    
КонецФункции

Важные моменты при работе с файлами

При использовании вышеуказанных методов следует учитывать несколько критически важных аспектов:

Подведем итог: прямое чтение реквизита ФайлХранилище — это устаревший подход, который не гарантирует получение данных в современных конфигурациях 1С. Использование стандартных функций БСП делает ваш код надежным, универсальным и защищенным от изменений в настройках хранения файлов (переход с базы данных на тома и обратно).

← На главную