Как перенести файлы из справочника присоединенных файлов в справочник «Файлы» в 1С:ERP?

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

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

Архитектурные особенности хранения файлов в 1С:ERP

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

  1. Внутри информационной базы в виде реквизита с типом ХранилищеЗначения.
  2. Во внешних томах хранения на диске (в сетевых папках), когда в базе сохраняется лишь относительный путь к файлу и ссылка на соответствующий том.

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


Способ 1. Использование штатного механизма БСП (Рекомендуемый)

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

Для выполнения переноса мы можем использовать метод РаботаСФайлами.ПеренестиФайлыМеждуСправочникамиХранения. Давайте разберем параметры этой процедуры:


// Синтаксис метода:
// РаботаСФайлами.ПеренестиФайлыМеждуСправочникамиХранения(ВладелецФайлов, Источник, Приемник)

Рассмотрим по шагам логику работы этого метода:

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

Обратите внимание, что устаревший метод РаботаСФайлами.ИзменитьСправочникХраненияФайлов, который использовался в старых версиях ERP (например, 2.4.7), начиная с БСП 3.2 полностью удален из конфигурации, поэтому использовать его в новых разработках крайне не рекомендуется.


Способ 2. Написание собственной обработки для переноса файлов через двоичные данные

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

Выясним причину, почему нельзя просто прочитать реквизит ХранимыйФайл запросом. Как уже упоминалось, при хранении файлов в томах прямой метод Выборка.ХранимыйФайл.Получить() вернет пустое значение. Чтобы избежать этой проблемы, мы должны использовать функцию РаботаСФайлами.ДвоичныеДанныеФайла, которая корректно извлекает данные независимо от настроек системы.

Давайте посмотрим на пример программного кода, выполняющего перенос файлов ресурсных спецификаций в общий справочник Файлы:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СпецификацииФайлы.Ссылка КАК ПрисоединенныйФайл,
    |	СпецификацииФайлы.ВладелецФайла КАК ВладелецФайла,
    |	СпецификацииФайлы.Наименование КАК Наименование,
    |	СпецификацииФайлы.Расширение КАК Расширение,
    |	СпецификацииФайлы.ДатаСоздания КАК ДатаСоздания,
    |	СпецификацииФайлы.Автор КАК Автор
    |ИЗ
    |	Справочник.РесурсныеСпецификацииПрисоединенныеФайлы КАК СпецификацииФайлы
    |ГДЕ
    |	НЕ СпецификацииФайлы.ПометкаУдаления";

Выборка = Запрос.Выполнить().Выбрать();

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

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


Способ 3. Перенос с изменением владельцев и структуры каталогов

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


Критически важные технические ограничения

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

1. Ограничения типов владельцев в справочнике «Файлы»

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

2. Безопасность и ограничение доступа (RLS)

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

3. Очистка базы данных

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

← На главную