При работе в конфигурациях на базе Библиотеки стандартных подсистем (БСП), таких как 1С:ERP 2.4/2.5, программисты часто сталкиваются с задачей копирования присоединенных файлов. Например, когда нужно перенести сертификаты или изображения из справочника Номенклатура в документ Сделка с клиентом. Обычное копирование реквизитов справочника ...ПрисоединенныеФайлы через ЗаполнитьЗначенияСвойств приводит к критической ошибке: файл отображается в списке, но при попытке открытия система сообщает, что двоичные данные удалены или недоступны.
В этой статье мы подробно разберем, почему так происходит, изучим внутреннюю архитектуру хранения файлов и реализуем правильный механизм копирования, который обеспечит сохранность данных.
Проанализируем ситуацию: в БСП информация о файле разделена на две части. Первая — это метаданные (элемент справочника НоменклатураПрисоединенныеФайлы), где хранятся имя, расширение, автор и дата создания. Вторая — это собственно двоичные данные. В зависимости от настроек системы, эти данные могут физически находиться либо в регистре сведений ДвоичныеДанныеФайлов, либо на диске (в томах хранения файлов).
Если мы просто создадим новый элемент справочника и скопируем в него ссылку на путь к файлу или идентификатор данных, мы создадим "зависимую" копию. Как только оригинальный объект (например, номенклатура) будет удален, регламентное задание по очистке ненужных файлов обнаружит, что основной владелец файла исчез, и физически удалит данные с диска или из регистра. Ваша копия в Сделках моментально станет "битой".
Вывод: для корректной работы необходимо создавать не только новую запись в справочнике, но и физическую копию самих двоичных данных.
Рассмотрим наиболее надежный способ решения задачи, основанный на использовании программного интерфейса БСП. Мы будем использовать модуль РаботаСФайлами (или ПрисоединенныеФайлы в зависимости от версии вашей БСП).
Разберем по шагам процесс копирования одного файла:
Посмотрим на пример кода, который реализует этот алгоритм:
// Предположим, у нас есть СсылкаНаФайлИсточник (Тип: СправочникСсылка.НоменклатураПрисоединенныеФайлы)
// И СсылкаНаНовыйВладелец (Тип: СправочникСсылка.СделкиСКлиентами)
// 1. Извлекаем двоичные данные. Метод универсален для томов и базы.
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайлИсточник);
// 2. Помещаем данные во временное хранилище
АдресФайлаВХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
// 3. Получаем метаданные исходного файла
РеквизитыФайла = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаФайлИсточник, "Наименование, Расширение, Автор");
// 4. Заполняем структуру параметров для создания нового файла
ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
ПараметрыФайла.ВладелецФайлов = СсылкаНаНовыйВладелец;
ПараметрыФайла.ИмяБезРасширения = РеквизитыФайла.Наименование;
ПараметрыФайла.РасширениеБезТочки = РеквизитыФайла.Расширение;
ПараметрыФайла.Автор = РеквизитыФайла.Автор;
// 5. Создаем новый файл
РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, АдресФайлаВХранилище);
Выясним, как реализовать цикл по всем прикрепленным файлам объекта. Это наиболее частый сценарий. Нам нужно выбрать все файлы, принадлежащие конкретной номенклатуре, и перенести их в сделку. Проанализируем пример кода для массовой обработки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| НоменклатураПрисоединенныеФайлы.Ссылка КАК Ссылка
|ИЗ
| Справочник.НоменклатураПрисоединенныеФайлы КАК НоменклатураПрисоединенныеФайлы
|ГДЕ
| НоменклатураПрисоединенныеФайлы.ВладелецФайла = &Владелец
| И НЕ НоменклатураПрисоединенныеФайлы.ПометкаУдаления";
Запрос.УстановитьПараметр("Владелец", МояНоменклатураСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем данные
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(Выборка.Ссылка);
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
// Подготовка параметров
ПараметрыДобавления = РаботаСФайлами.ПараметрыДобавленияФайла();
ПараметрыДобавления.ВладелецФайлов = СделкаСсылка;
ПараметрыДобавления.ИмяБезРасширения = Выборка.Ссылка.Наименование;
ПараметрыДобавления.РасширениеБезТочки = Выборка.Ссылка.Расширение;
// Добавление файла в новый объект
РаботаСФайлами.ДобавитьФайл(ПараметрыДобавления, АдресХранилища);
КонецЦикла;
Рассмотрим подробнее несколько критических моментов, которые часто упускают при разработке:
1. Работа с электронными подписями (ЭЦП). Если ваши файлы в 1С:ERP подписаны электронными подписями, метод ДобавитьФайл скопирует только сам файл, но не подписи к нему. Подписи хранятся в отдельном регистре. Чтобы перенести их, необходимо использовать метод: РаботаСЭлектроннойПодписью.СкопироватьПодписи(Источник, Приемник). Без этого юридическая значимость копии будет утрачена.
2. Версионирование файлов. Если в справочнике-источнике включено хранение версий, при использовании вышеуказанного кода вы скопируете только текущую активную версию файла. Если бизнес-логика требует переноса всей истории изменений, вам придется программно перебирать справочник ...ВерсииФайлов и создавать версии для нового объекта вручную, что значительно сложнее.
3. Права доступа. Файлы в БСП наследуют права от своих владельцев. Если у пользователя, запускающего код, нет прав на чтение справочника Номенклатура, метод ДвоичныеДанныеФайла может вернуть ошибку или пустое значение. При выполнении кода в фоновых заданиях или под регламентным пользователем убедитесь в наличии соответствующих прав.
4. Оптимизация памяти. Помещение больших файлов (например, сканов чертежей высокого разрешения) во временное хранилище может привести к резкому росту потребления оперативной памяти на сервере 1С. Если вы копируете сотни тяжелых файлов за один раз, рекомендуется периодически очищать временное хранилище или выполнять операцию в привилегированном модуле порциями.
Мы проанализировали механизм работы с присоединенными файлами в 1С и выяснили, что безопасное копирование возможно только через создание физической копии данных. Использование стандартных методов БСП, таких как РаботаСФайлами.ДобавитьФайл, гарантирует, что система правильно пропишет все связи, создаст записи в регистрах сведений или файлы в томах и обеспечит корректную работу поиска по текстам файлов.
Используйте этот подход, чтобы ваши данные всегда оставались доступными, даже если исходные объекты будут удалены из системы.