При разработке систем документооборота или личных кабинетов часто возникает задача: проверить, все ли обязательные документы загружены пользователем, и нет ли в папке (или хранилище) посторонних файлов, которые не относятся к делу. Например, если ожидаются только «Скан_Паспорта» и «Копия_ИНН», программа должна уметь сигнализировать о наличии любого третьего файла. В этой статье мы подробно разберем, как реализовать такую проверку, используя встроенные возможности платформы 1С:Предприятие 8.3.
Если нам заранее известно имя файла, который мы ищем, самым простым и быстрым способом будет использование объекта Файл. Рассмотрим ситуацию, когда нам нужно просто убедиться, что файл с определенным именем существует на диске.
Разберем пример кода:
ПолноеИмяФайла = "C:\Docs\Passport.pdf";
ОбъектФайл = Новый Файл(ПолноеИмяФайла);
Если Не ОбъектФайл.Существует() Тогда
Сообщить("Файл не найден!");
Иначе
Сообщить("Файл успешно обнаружен. Размер: " + ОбъектФайл.Размер());
КонецЕсли;
Этот метод хорош для точечной проверки, но он не подходит, если нам нужно найти «лишние» файлы, имен которых мы не знаем. Для этого нам потребуется просканировать весь каталог.
Для того чтобы понять, есть ли в папке файлы, не входящие в наш «белый список», мы воспользуемся методом НайтиФайлы. Этот метод возвращает массив объектов типа Файл, который мы можем перебрать в цикле и проанализировать.
Проанализируем ситуацию: у нас есть массив разрешенных имен, и нам нужно вывести предупреждение, если в папке обнаружено что-то иное. Реализуем это следующим образом:
ПутьККаталогу = "C:\Uploads\";
МассивРазрешенныхИмен = Новый Массив;
МассивРазрешенныхИмен.Добавить("Passport.jpg");
МассивРазрешенныхИмен.Добавить("INN.jpg");
// Получаем список всех файлов в папке по маске * (все файлы)
НайденныеФайлы = НайтиФайлы(ПутьККаталогу, "*.*");
Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
// Проверяем, не является ли объект каталогом
Если ТекущийФайл.ЭтоКаталог() Тогда
Продолжить;
КонецЕсли;
// Ищем имя текущего файла в списке разрешенных
Если МассивРазрешенныхИмен.Найти(ТекущийФайл.Имя) = Неопределено Тогда
Сообщить("Внимание! Обнаружен посторонний файл: " + ТекущийФайл.Имя);
КонецЕсли;
КонецЦикла;
Если список разрешенных файлов содержит десятки или сотни наименований, поиск методом Массив.Найти() внутри цикла может существенно замедлить работу системы. В 1С для таких задач эффективнее использовать объект Соответствие, который работает по принципу хеш-таблицы.
Рассмотрим, как ускорить нашу проверку:
СписокДопустимых = Новый Соответствие;
СписокДопустимых.Вставить("passport.png", Истина);
СписокДопустимых.Вставить("inn.png", Истина);
СписокДопустимых.Вставить("snils.png", Истина);
НайденныеФайлы = НайтиФайлы(ПутьККаталогу, "*.*");
Для Каждого ФайлИзПапки Из НайденныеФайлы Цикл
// Поиск в соответствии происходит практически мгновенно
Если СписокДопустимых.Получить(НРег(ФайлИзПапки.Имя)) = Неопределено Тогда
Сообщить("Найден неизвестный файл: " + ФайлИзПапки.Имя);
КонецЕсли;
КонецЦикла;
Важный момент: При сравнении имен файлов всегда используйте функцию НРег() (приведение к нижнему регистру), так как файловые системы Windows нечувствительны к регистру, а сравнение строк в 1С — чувствительно.
Иногда имена файлов не фиксированы жестко, а строятся по шаблону, например: «Паспорт_Иванов.pdf» или «Справка_2023_01.jpg». В таких случаях простое сравнение строк не поможет. Выясним, как применить регулярные выражения через COM-объект VBScript.RegExp.
Посмотрим на пример кода, который проверяет, соответствует ли файл шаблону «Слово_Цифры»:
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
RegExp.Pattern = "^(Паспорт|ИНН)_[0-9]+\.(jpg|pdf)$"; // Шаблон: Имя_Число.расширение
НайденныеФайлы = НайтиФайлы(ПутьККаталогу, "*.*");
Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
Если Не RegExp.Test(ТекущийФайл.Имя) Тогда
Сообщить("Файл '" + ТекущийФайл.Имя + "' не соответствует стандарту именования!");
КонецЕсли;
КонецЦикла;
В современных конфигурациях 1С, работающих через веб-клиент или в тонком клиенте с жесткими требованиями к безопасности, использование синхронного метода НайтиФайлы может быть ограничено или приводить к «замиранию» интерфейса. В таких случаях правильно использовать асинхронные методы.
Разберем алгоритм работы с НачатьПоискФайлов. Этот метод не возвращает результат сразу, а вызывает процедуру-обработчик (описание оповещения) после завершения операции.
&НаКлиенте
Процедура ПроверитьФайлыАсинхронно()
Оповещение = Новый ОписаниеОповещения("ПослеПоискаФайлов", ЭтотОбъект);
НачатьПоискФайлов(Оповещение, "C:\MyFolder", "*.*", Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПоискаФайлов(МассивФайлов, ДополнительныеПараметры) Экспорт
Для Каждого ТекущийФайл Из МассивФайлов Цикл
// Здесь выполняется логика фильтрации
Сообщить("Найден файл: " + ТекущийФайл.Имя);
КонецЦикла;
КонецПроцедуры
Если вы работаете в типовой конфигурации (например, ERP, УТ 11 или БП 3.0), настоятельно рекомендуем использовать механизмы подсистемы «Работа с файлами». В БСП уже реализованы функции для получения расширений, нормализации имен и даже запрета загрузки определенных типов файлов (например, исполняемых .exe или .bat).
Использование готовых функций БСП позволяет избежать ошибок при ручном парсинге строки пути. Например, для получения расширения файла лучше использовать ОбщегоНазначенияКлиентСервер.ПолучитьРасширениеИмениФайла().
Завершая наш разбор, выделим несколько практических советов для создания качественного интерфейса проверки:
ОпределениеТипаФайла для анализа бинарных данных заголовка.ОписаниеПередаваемогоФайла до того, как они будут переданы на сервер. Это сэкономит трафик и ресурсы сервера.Используя предложенные методы, мы можем построить надежную систему контроля вложений, которая обеспечит порядок в хранилище документов и предотвратит попадание посторонних данных в информационную базу.