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