Почему функция НайтиФайлы возвращает только путь к каталогу вместо списка файлов

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

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

Разбор типовой ситуации и поиск причины

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


&НаКлиенте
Процедура ЗаполнитьИзФайловXLS(Команда)
    // ПутьККаталогу содержит строку, например, "C:\MyFiles"
    МассивНайденных = НайтиФайлы(ЭтотОбъект.ПутьККаталогу); 
    Для Каждого Файл из МассивНайденных Цикл 
        ЗаполнитьИзФайловXLSНаСервере(Файл.ИмяФайла);
    КонецЦикла;
КонецПроцедуры

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

Как правильно задать маску поиска

Чтобы функция вернула содержимое каталога, необходимо явно указать Маску. Рассмотрим исправленный вариант кода, где мы ищем только файлы электронных таблиц с расширением .xls:


// Правильное использование с указанием маски
МассивНайденных = НайтиФайлы(ЭтотОбъект.ПутьККаталогу, "*.xls");

Если нам требуется получить абсолютно все файлы и вложенные папки, содержащиеся в каталоге, мы можем использовать универсальную маску * или *.*. Важно понимать разницу:

  1. Если маска не задана, а путь ведет к каталогу — возвращается информация о каталоге.
  2. Если задана маска *.* — возвращаются все файлы, имеющие расширение.
  3. Если задана маска * — возвращаются все файлы и все вложенные папки.

Использование свойств объекта Файл для фильтрации

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


МассивНайденных = НайтиФайлы(ЭтотОбъект.ПутьККаталогу, "*"); 
Для Каждого ТекущийОбъект из МассивНайденных Цикл 
    Если ТекущийОбъект.ЭтоФайл() Тогда
        // Обрабатываем только файлы
        Сообщить("Найден файл: " + ТекущийОбъект.ПолноеИмя);
    ИначеЕсли ТекущийОбъект.ЭтоКаталог() Тогда
        // Пропускаем или обрабатываем вложенные папки
        Сообщить("Найдена папка: " + ТекущийОбъект.Имя);
    КонецЕсли;
КонецЦикла;

Помимо типа объекта, мы можем использовать метод Размер() для исключения пустых файлов или ПолучитьВремяИзменения(), чтобы обрабатывать только самые свежие документы.

Асинхронные методы в современном интерфейсе

Разберем важный нюанс работы в современных версиях платформы (8.3.15 и выше). При работе в тонком или веб-клиенте использование синхронного метода НайтиФайлы() может привести к блокировке интерфейса или ошибкам безопасности в браузере. В таких случаях настоятельно рекомендуется использовать асинхронный аналог — НайтиФайлыАсинх().

Этот метод работает через механизм "Обещаний" (Promises). Посмотрим, как может выглядеть современная реализация:


&НаКлиенте
Асинх Процедура ЗаполнитьИзФайловXLSАсинх(Команда)
    МассивНайденных = Ждать НайтиФайлыАсинх(ЭтотОбъект.ПутьККаталогу, "*.xls");
    Для Каждого Файл из МассивНайденных Цикл 
        // Дальнейшая логика обработки
    КонецЦикла;
КонецПроцедуры

Важно: Для работы с локальными файлами пользователя в веб-клиенте обязательно должно быть установлено расширение работы с файлами.

Особенности кроссплатформенной разработки (Windows и Linux)

Если ваша база 1С работает на сервере под управлением Linux, следует учитывать регистрозависимость файловой системы. Рассмотрим основные отличия:

Рекурсивный поиск в подкаталогах

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


// Поиск во всех вложенных папках
МассивНайденных = НайтиФайлы(ЭтотОбъект.ПутьККаталогу, "*.xls", Истина);

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

← На главную