Почему метод Добавить объекта ЗаписьZipФайла вызывает ошибку при архивации файлов по маске?

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

При программной работе с ZIP-архивами в платформе 1С:Предприятие разработчики часто используют маски файлов (например, *.xml или *.*) для быстрой групповой упаковки содержимого каталога. Однако при выполнении метода Добавить() объекта ЗаписьZipФайла может возникать непредвиденная ошибка времени выполнения, прерывающая обмен данными или выгрузку документов.

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

Причина возникновения ошибки при добавлении по маске

Рассмотрим типовой фрагмент кода, где вызывается архивация:


ЗаписьАрхива.Добавить(КаталогДляВыгрузки + "\*.xml", 
    РежимСохраненияПутейФайлаАрхива.НеСохранятьПути, 
    РежимОбработкиПодкаталоговФайлаАрхива.НеОбрабатывать);

Если в указанном каталоге физически отсутствуют файлы с расширением .xml, платформа 1С штатно генерирует исключение: Файл не найден. Метод Добавить() ожидает обязательного наличия хотя бы одного файла, удовлетворяющего переданному шаблону.

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

Кроме того, важно помнить об ограничении платформы: пустой ZIP-архив средствами объекта ЗаписьZipФайла записать невозможно. Если в архив не было добавлено ни одного файла, последующий вызов метода Записать() также приведет к ошибке.

Способ 1. Предварительная проверка наличия файлов через функцию НайтиФайлы

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

Посмотрим на пример реализации:


НайденныеФайлы = НайтиФайлы(КаталогДляВыгрузки, "*.xml");

Если НайденныеФайлы.Количество() > 0 Тогда
    ЗаписьАрхива.Добавить(КаталогДляВыгрузки + "\*.xml", 
        РежимСохраненияПутейФайлаАрхива.НеСохранятьПути, 
        РежимОбработкиПодкаталоговФайлаАрхива.НеОбрабатывать);
    
    // Записываем архив только при наличии добавленных файлов
    ЗаписьАрхива.Записать();
Иначе
    // Файлы для архивации отсутствуют, выполняем альтернативное действие
    ЗаписьЖурналаРегистрации("Выгрузка данных", УровеньЖурналаРегистрации.Предупреждение,,, 
        "Файлы для архивации по маске *.xml не обнаружены.");
КонецЕсли;

Такой подход защищает код сразу от двух проблем: исключения при поиске по маске и ошибки при попытке сохранить пустой архив.

Способ 2. Пофайловое добавление найденных элементов в цикле

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

Разберем по шагам данный алгоритм:

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

Посмотрим на пример кода:


НайденныеФайлы = НайтиФайлы(КаталогДляВыгрузки, "*.xml");

Если НайденныеФайлы.Количество() > 0 Тогда
    Для Каждого Файл Из НайденныеФайлы Цикл
        ЗаписьАрхива.Добавить(Файл.ПолноеИмя, 
            РежимСохраненияПутейФайлаАрхива.НеСохранятьПути, 
            РежимОбработкиПодкаталоговФайлаАрхива.НеОбрабатывать);
    КонецЦикла;
    
    ЗаписьАрхива.Записать();
КонецЕсли;

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

Способ 3. Перехват исключения через конструкцию Попытка — Исключение

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

Рассмотрим подробнее реализацию:


ФайлыДобавлены = Ложь;

Попытка
    ЗаписьАрхива.Добавить(КаталогДляВыгрузки + "\*.xml", 
        РежимСохраненияПутейФайлаАрхива.НеСохранятьПути, 
        РежимОбработкиПодкаталоговФайлаАрхива.НеОбрабатывать);
    ФайлыДобавлены = Истина;
Исключение
    // Каталог пуст либо файлы по указанной маске не найдены
    ИнформацияОбОшибке = ОписаниеОшибки();
КонецПопытки;

Если ФайлыДобавлены Тогда
    ЗаписьАрхива.Записать();
КонецЕсли;

Важный момент: флаг ФайлыДобавлены обязателен, чтобы не вызвать метод Записать() у объекта, в который не было помещено ни одного файла.

Способ 4. Комплексная проверка существования каталога и прав доступа

Иногда ошибка возникает не только из-за отсутствия файлов, но и по причине некорректного пути или отсутствия прав на просмотр содержимого папки у учетной записи, под которой запущен кластер серверов 1С.

Проанализируем безопасный шаблон инициализации перед началом архивации:


ПапкаНаДиске = Новый Файл(КаталогДляВыгрузки);

Если ПапкаНаДиске.Существует() И ПапкаНаДиске.ЭтоКаталог() Тогда
    НайденныеФайлы = НайтиФайлы(КаталогДляВыгрузки, "*.xml");
    Если НайденныеФайлы.Количество() > 0 Тогда
        ЗаписьАрхива.Добавить(КаталогДляВыгрузки + "\*.xml", 
            РежимСохраненияПутейФайлаАрхива.НеСохранятьПути, 
            РежимОбработкиПодкаталоговФайлаАрхива.НеОбрабатывать);
        ЗаписьАрхива.Записать();
    КонецЕсли;
Иначе
    ВызватьИсключение "Указанный каталог выгрузки не существует: " + КаталогДляВыгрузки;
КонецЕсли;

Использование связки проверки существования каталога и поиска файлов через НайтиФайлы() полностью предотвращает аварийные падения при упаковке данных в ZIP-архивы.

← На главную