Как правильно записать несколько файлов в один ZIP-архив в 1С?

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

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

Почему в архив попадает только последний файл?

Проанализируем типовой фрагмент кода, приводящий к ошибке:


Для Каждого Файл Из МассивФайлов Цикл
    ЗаписьZIP = Новый ЗаписьZipФайла(ИмяФайлаАрхива);
    ЗаписьZIP.Добавить(Файл);
    ЗаписьZIP.Записать();
КонецЦикла;

В приведенном коде допущены две критические ошибки логики работы с объектом ЗаписьZipФайла:

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

Вариант 1. Поочередное добавление файлов в один объект архива

Самый простой и прямолинейный способ упаковки нескольких файлов, разбросанных по разным путям или хранящихся в виде массива имен, — вынести создание и закрытие архива за пределы цикла добавления.

Посмотрим на пример правильного пошагового наполнения архива:


ИмяФайлаАрхива = "C:\Temp\ПакетДокументов.zip";

// Инициализируем архив один раз до начала цикла
ЗаписьZIP = Новый ЗаписьZipФайла(ИмяФайлаАрхива);

// Добавляем файлы по очереди
ЗаписьZIP.Добавить("C:\Temp\Накладная_1.xlsx");
ЗаписьZIP.Добавить("C:\Temp\Накладная_2.xlsx");
ЗаписьZIP.Добавить("C:\Temp\Счет_3.xlsx");

// Финализируем архив один раз после добавления всех файлов
ЗаписьZIP.Записать();

Если список файлов динамический, организуем аналогичную операцию в цикле:


ИмяФайлаАрхива = КаталогВременныхФайлов() + "Выгрузка.zip";
ЗаписьZIP = Новый ЗаписьZipФайла(ИмяФайлаАрхива);

Для Каждого ИмяФайла Из СписокПутейКФайлам Цикл
    // Метод Добавить принимает путь к файлу и способ сохранения путей
    ЗаписьZIP.Добавить(ИмяФайла, РежимСохраненияПутейZIP.НеСохранятьПути);
КонецЦикла;

// Закрываем и сохраняем архив на диске
ЗаписьZIP.Записать();

Обратите внимание на второй параметр метода Добавить(): перечисление РежимСохраненияПутейZIP.НеСохранятьПути гарантирует, что все файлы внутри архива попадут непосредственно в корень архива без воссоздания структуры папок вашего жесткого диска.

Вариант 2. Архивирование выделенного каталога или по маске

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

Разберем по шагам, как подготовить отдельную временную папку и упаковать её содержимое:


КаталогВременныхФайлов = КаталогВременныхФайлов(); 
КаталогДляФайлов = КаталогВременныхФайлов + "ЭкспортXLS\";

// 1. Проверяем существование каталога и создаем его при необходимости
КаталогНаДиске = Новый Файл(КаталогДляФайлов);
Если Не КаталогНаДиске.Существует() Тогда
    СоздатьКаталог(КаталогДляФайлов);
КонецЕсли;

// 2. Здесь происходит формирование и сохранение файлов в КаталогДляФайлов...
// Например: ТабличныйДокумент.Записать(КаталогДляФайлов + "Отчет.xlsx", ТипФайлаТабличногоДокумента.XLSX);

// 3. Создаем ZIP-архив и упаковываем каталог
ПутьКАрхиву = КаталогВременныхФайлов + "ИтоговыйАрхив.zip";
Архиватор = Новый ЗаписьZipФайла(ПутьКАрхиву);

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

// 4. Очищаем временную папку после упаковки при необходимости
УдалитьФайлы(КаталогДляФайлов);

Важные практические нюансы и рекомендации

При промышленной эксплуатации процедур архивации важно учитывать технические ограничения платформы 1С:

  1. Блокировка исходных файлов сторонними программами. Если один из файлов Excel открыт пользователем на локальном компьютере в момент добавления, платформа вызовет исключение ошибки совместного доступа. Рекомендуется оборачивать процедуру архивации в блок Попытка ... Исключение с выводом понятного сообщения пользователю.
  2. Дублирование имен при отсутствии путей. При использовании режима РежимСохраненияПутейZIP.НеСохранятьПути следите за тем, чтобы добавляемые файлы из разных каталогов не имели одинаковых имен, иначе более поздний файл перезапишет предыдущий внутри архива.
  3. Работа на сервере без сохранения на диск. Если функционал выполняется в серверном коде или веб-клиенте, можно работать через поток в оперативной памяти (ПотокВПамяти), передавая его первым параметром в конструктор ЗаписьZipФайла. Это исключает проблемы с правами на запись во временные каталоги файловой системы сервера.
← На главную