Как программно прикрепить файл к объекту в БСП и исправить ошибку "Не заполнен владелец в файле"?

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

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

В этой статье мы подробно разберем, почему возникают эти ошибки, как устроена архитектура хранения файлов в БСП и как правильно писать лаконичный и работоспособный код для программного добавления файлов.

Две параллельные системы хранения файлов в БСП

Для начала проанализируем архитектурную особенность БСП, которая часто вводит разработчиков в заблуждение. В библиотеке сосуществуют два принципиально разных механизма для работы с файлами:

  1. Общий контейнер (подсистема «Работа с файлами»): Все файлы системы загружаются и хранятся в одном общем справочнике Справочники.Файлы. Эта схема удобна тем, что поддерживает сложную иерархию папок, версионирование и единые механизмы очистки. Но у нее есть существенный минус — сложность разграничения прав доступа на уровне записей (RLS) для разных типов документов и справочников.
  2. Индивидуальные контейнеры (подсистема «Присоединенные файлы»): Для каждого прикладного объекта-владельца (например, справочника Номенклатура или документа РеализацияТоваровУслуг) создается собственный выделенный справочник по шаблону [ИмяВладельца]ПрисоединенныеФайлы. Это позволяет легко наследовать права доступа от самого владельца, но убирает иерархическую структуру папок.

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

Выясняем причину ошибки "Не заполнен владелец..."

Рассмотрим ситуацию, в которой оказался автор темы. При попытке вызвать метод:


РаботаСФайлами.СоздатьФайлНаОсновеФайлаНаДиске(ВладелецФайлов, ПутьКФайлуНаДиске)

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

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

Почему же тогда передача ссылки на саму Номенклатуру вызывала ошибку? Все дело в отсутствии связи в определяемых типах.

Пошаговая настройка определяемых типов в Конфигураторе

Чтобы универсальные механизмы БСП понимали, в какой именно справочник нужно положить файл для конкретного типа объекта, этот объект должен быть правильно зарегистрирован в метаданных. Если вы создаете свой объект или дорабатываете типовой, обязательно проверьте заполнение следующих определяемых типов в конфигураторе:

  1. ВладелецПрисоединенныхФайлов — сюда необходимо добавить ссылку на ваш объект-владелец (например, СправочникСсылка.Номенклатура или ДокументСсылка.НашНовыйДокумент).
  2. ВладелецПрисоединенныхФайловОбъект — добавьте сюда объектный тип вашего владельца (например, СправочникОбъект.Номенклатура или ДокументОбъект.НашНовыйДокумент).
  3. ПрисоединенныйФайл — в этот тип должна входить ссылка на ваш подчиненный справочник хранения файлов (например, СправочникСсылка.НоменклатураПрисоединенныеФайлы).
  4. ПрисоединенныйФайлОбъект — объектная версия подчиненного справочника (СправочникОбъект.НоменклатураПрисоединенныеФайлы).
  5. ПереопределитьПолучаемуюФормуПрисоединенногоФайла — укажите менеджер вашего справочника присоединенных файлов (СправочникМенеджер.НоменклатураПрисоединенныеФайлы).

Как только эти связи будут настроены, БСП с помощью внутренних алгоритмов сможет по типу переданного владельца мгновенно вычислить имя нужной таблицы для записи физических данных.

Актуальные программные методы работы с файлами

Метод РаботаСФайлами.СоздатьФайлНаОсновеФайлаНаДиске в современных редакциях БСП признан устаревшим (deprecated). Нам крайне не рекомендуется использовать его в новом коде, так как в будущих обновлениях библиотеки он может быть полностью удален.

Вместо него рассмотрим два современных и надежных сценария работы.

Сценарий 1. Быстрое добавление файла с диска

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

Посмотрим на пример кода:


// Ссылка на объект, к которому прикрепляем файл (например, Номенклатура)
ВладелецКартинки = Справочники.Номенклатура.НайтиПоКоду("00000001");
ПутьКФайлуНаСервере = "C:\Temp\picture.png";

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

Сценарий 2. Универсальное добавление через временное хранилище

Часто в веб-клиенте или при передаче данных в фоновые задания файлы передаются через механизм временного хранилища. В таких случаях мы используем метод РаботаСФайлами.ДобавитьФайл.

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

Разберем этот процесс по шагам в следующем примере кода:


// Шаг 1. Получаем структуру параметров с заполненными значениями по умолчанию
ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();

// Шаг 2. Заполняем только ключевые свойства
ПараметрыФайла.ВладелецФайлов      = СсылкаНаНоменклатуру;
ПараметрыФайла.ИмяБезРасширения    = "Инструкция_По_Эксплуатации";
ПараметрыФайла.РасширениеБезТочки  = "pdf";

// Шаг 3. Помещаем двоичные данные файла во временное хранилище
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла);

// Шаг 4. Вызываем метод БСП для добавления файла
СсылкаНаНовыйФайл = РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, АдресХранилища);

Этот подход лаконичен, безопасен и полностью соответствует стандартам разработки фирмы "1С".

Продвинутый прием: Явное указание целевого справочника

Что делать, если у одного объекта-владельца может быть несколько разных подчиненных справочников для хранения файлов, либо вы не хотите/не можете менять определяемые типы в конфигурации?

У метода РаботаСФайлами.ДобавитьФайл есть недокументированная, но крайне полезная возможность — использование пятого параметра НоваяСсылкаНаФайл. Мы можем предварительно сгенерировать пустую ссылку нужного справочника хранения на основе нашей метаданной и передать ее функции. В этом случае БСП минует автоматическое определение и запишет данные строго по указанному адресу.

Проанализируем пример такой реализации:


ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
ПараметрыФайла.ВладелецФайлов      = СсылкаНаНоменклатуру;
ПараметрыФайла.ИмяБезРасширения    = "Сертификат_Соответствия";
ПараметрыФайла.РасширениеБезТочки  = "jpg";

// Генерируем уникальную ссылку в конкретном справочнике хранения присоединенных файлов
ЦелеваяСсылка = Справочники.НоменклатураПрисоединенныеФайлы.ПолучитьСсылку();

// Передаем сформированную ссылку в качестве 5-го параметра
СсылкаНаНовыйФайл = РаботаСФайлами.ДобавитьФайл(
    ПараметрыФайла, 
    АдресХранилища, 
    "", 
    "Описание файла сертификата", 
    ЦелеваяСсылка
);

Используя этот прием, вы полностью контролируете процесс записи и гарантированно избегаете ошибок сопоставления типов в сложных или нетиповых конфигурациях.

← На главную