При активном обмене данными через FTP-серверы разработчики 1С часто сталкиваются с ситуацией, когда в одной директории скапливается огромное количество файлов (от 10 000 и выше). В определенный момент стандартные механизмы платформы, такие как метод НайтиФайлы объекта FTPСоединение, перестают возвращать полный список объектов или выдают ошибку. Рассмотрим подробнее, почему это происходит и какими способами можно решить данную проблему.
Распространенное заблуждение гласит, что это внутреннее ограничение платформы 1С. Однако на практике ситуация сложнее. Проанализируем основные факторы, влияющие на этот лимит:
ListOptions или аналогичные настройки лимитов. Для обеспечения стабильности системы хостеры ограничивают количество объектов, возвращаемых по команде LIST, числом 10 000 или даже меньше.Если ваша задача заключается в удалении файлов, имена которых уже известны в базе данных 1С (например, они хранятся в регистре сведений или справочнике), вам вообще не нужно использовать метод НайтиФайлы. Рассмотрим, как это работает: метод Удалить объекта FTPСоединение работает по прямому пути к файлу. Серверу не нужно сканировать всю папку, чтобы выполнить эту команду.
Проанализируем пример кода для прямого удаления:
// Предположим, СписокФайловНаУдаление - это массив имен файлов из базы 1С
FTP = Новый FTPСоединение(Сервер, Порт, Логин, Пароль, , Истина); // Пассивный режим
Для Каждого ИмяФайла Из СписокФайловНаУдаление Цикл
Попытка
ПолныйПуть = "/exchange/orders/" + ИмяФайла;
FTP.Удалить(ПолныйПуть);
Исключение
ЗаписьЖурналаРегистрации("FTP_Ошибка", УровеньЖурналаРегистрации.Предупреждение, , ,
"Не удалось удалить файл: " + ИмяФайла + ". Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Важный момент: Этот способ полностью обходит лимит листинга (отображения), так как команда на удаление отправляется точечно.
Если же вам необходимо именно получить список файлов, чтобы понять, что накопилось на сервере, а общее количество превышает лимит хостинга, мы можем применить метод «разделяй и властвуй». Разберем по шагам: вместо запроса всех файлов *.*, мы будем запрашивать их порциями, используя маски имен.
Посмотрим на пример реализации перебора по алфавиту:
Функция ПолучитьВсеФайлыЧерезМаски(FTPСоединение, ПутьКПапке)
МассивРезультатов = Новый Массив;
СимволыДляМаски = "0123456789abcdefghijklmnopqrstuvwxyz";
Для Итератор = 1 По СтрДлина(СимволыДляМаски) Цикл
ТекущийСимвол = Сред(СимволыДляМаски, Итератор, 1);
Маска = ТекущийСимвол + "*.*";
НайденныеФайлы = FTPСоединение.НайтиФайлы(ПутьКПапке, Маска);
Для Каждого Файл Из НайденныеФайлы Цикл
МассивРезультатов.Добавить(Файл);
КонецЦикла;
КонецЦикла;
Возвращает МассивРезультатов;
КонецФункции
Этот алгоритм заставляет сервер каждый раз отдавать только малую часть списка, которая гарантированно впишется в настройки ListOptions хостинга.
Как отмечали участники обсуждения, «благородная идея запнулась», но именно разбиение файлов по подпапкам является промышленным стандартом. Если у вас есть возможность изменить логику выгрузки файлов на FTP, обязательно внедрите иерархическую структуру.
Рассмотрим варианты организации структуры:
/2023/10/25/file.xml/ab/cd/abcdef12345.xml/orders/, /invoices/, /logs/В 1С создание директории выполняется методом FTPСоединение.СоздатьКаталог(). Проанализируем ситуацию: даже если файлов будет миллион, в каждой конкретной папке их будет всего несколько сотен, что обеспечит мгновенную работу НайтиФайлы.
Если штатное FTPСоединение не справляется или работает слишком медленно, проанализируем использование внешних инструментов. Одним из самых надежных вариантов является библиотека WinSCP.
Преимущества использования WinSCP через COM-объект:
Также можно рассмотреть использование консольной утилиты curl. Мы можем сформировать текстовый файл со списком команд и выполнить его одной командой ОС через ЗапуститьПриложение(), что будет значительно быстрее, чем построчный перебор в цикле 1С.
Мы выяснили, что проблема «9999 файлов» чаще всего кроется в настройках сервера, а не в 1С. Для решения проблемы мы рекомендуем: