Как программно прикрепить файл к номенклатуре в 1С:Управлении торговлей 11? Разбор ошибок и метод БСП

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

При импорте данных, интеграции с интернет-магазинами или загрузке прайс-листов перед разработчиком часто возникает задача привязать изображения или сертификаты к карточкам номенклатуры. В современных конфигурациях «1С:Предприятие 8» на базе БСП (таких как «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация») файлы хранятся в подчиненных справочниках вида ИмяОбъектаПрисоединенныеФайлы.

Попытка создать такой элемент «в лоб» через стандартный метод СоздатьЭлемент() часто приводит к ошибкам работы с файловой системой. Разберем типичные ошибки ручного создания элементов справочника присоединенных файлов, выясним причины сбоев и детально рассмотрим два пути решения: исправление ручной записи и правильный архитектурный метод через программный интерфейс БСП.

Анализ проблемы: почему возникает ошибка «двоичные данные были удалены»?

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

«Не удалось открыть файл... по причине: двоичные данные файла были удалены. Возможно, файл очищен как ненужный или удален антивирусной программой.»

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

Вариант 1. Исправление ручного создания элемента справочника (быстрый путь)

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

Проанализируем готовый рабочий код ручного добавления файла, к которому пришел автор темы после исправления всех ошибок:


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

Рассмотрим подробнее ключевые моменты, которые были исправлены в данном коде по сравнению с первоначальной неудачной попыткой:

  1. Определение типа владельца: Реквизит ВладелецФайла имеет определяемый тип ОпределяемыеТипы.ВладелецПрисоединенныхФайлов. Прямое присвоение ссылки номенклатуры может вызвать конфликт типов в некоторых версиях платформы, поэтому перед записью мы явно приводим тип с помощью объекта ОписаниеТипов.
  2. Разделение пути к файлу: Реквизит ПутьКФайлу не должен содержать полный путь операционной системы (например, D:\Shares\1C_Files\Tom1\Catalog\image.jpg). В нем должен храниться только относительный путь внутри тома (например, Catalog\image.jpg). Путь к самому тому определяется через реквизит Том.
  3. Корректное заполнение тома: В реквизит Том необходимо передавать ссылку на элемент справочника томов хранения файлов, а не строковое представление или объект описания тома.
  4. Заполнение технических свойств файла: Важно заполнить размер файла, расширение без точки, дату модификации на диске и универсальную дату модификации. Эти данные считываются с помощью встроенного объекта платформы Файл.

Почему ручное создание файлов — это мина замедленного действия?

Несмотря на то, что приведенный выше ручной код работает, использовать его в реальных задачах крайне не рекомендуется по следующим причинам:

Вариант 2. Правильное решение через программный интерфейс БСП (модуль РаботаСФайлами)

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

Рассмотрим по шагам правильный алгоритм добавления файла к номенклатуре:


// 1. Помещаем двоичные данные файла во временное хранилище
ДвоичныеДанные = Новый ДвоичныеДанные(ПолныйПутьКФайлуНаДиске);
АдресВХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанные);

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

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

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

Проанализируем преимущества данного подхода:

Резюме

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

← На главную