К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как сжать файл в ZIP в 1С

Как сжать файл в ZIP в 1С: объект ЗаписьZipФайла, примеры кода, добавление нескольких файлов, пароль, распаковка и типичные ошибки.

Сжатие файлов в ZIP-архив — стандартная задача в 1С:Предприятии 8.3, которая решается встроенными средствами платформы без внешних архиваторов и COM-объектов. Для этого используются объекты ЗаписьZipФайла и ЧтениеZipФайла, доступные как на сервере, так и на клиенте.

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

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

Базовый пример: сжать один файл в ZIP

Минимальный рабочий код состоит из трёх шагов: открыть архив на запись, добавить в него файл, записать результат на диск. Объект ЗаписьZipФайла создаётся конструктором Новый ЗаписьZipФайла().

ЗаписьZIP = Новый ЗаписьZipФайла("C:\Temp\Архив.zip");

ЗаписьZIP.Добавить("C:\Temp\Отчет.xlsx");

ЗаписьZIP.Записать();

После выполнения Записать() файл Архив.zip появится в указанном каталоге. Если вызвать Записать() без параметров, архив сохранится по пути, заданному в конструкторе. Можно передать путь и явно: ЗаписьZIP.Записать("C:\Temp\Другой.zip").

Важно: пока не вызван метод Записать(), файл архива физически не существует — все операции накапливаются в памяти или во временном хранилище. Если код прервётся с ошибкой до вызова Записать(), архив не создастся вообще, а не окажется «полузаписанным».

bsl
ЗаписьZIP = Новый ЗаписьZipФайла("C:\Temp\Архив.zip");
ЗаписьZIP.Добавить("C:\Temp\Отчет.xlsx");
ЗаписьZIP.Записать();

Сжатие нескольких файлов и каталогов

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

ЗаписьZIP = Новый ЗаписьZipФайла("C:\Temp\Пакет.zip");

ЗаписьZIP.Добавить("C:\Temp\Документ1.pdf");

ЗаписьZIP.Добавить("C:\Temp\Документ2.pdf");

ЗаписьZIP.Добавить("C:\Temp\Выгрузки\", РежимСохраненияПутейZIP.СохранятьОтносительныеПути);

ЗаписьZIP.Записать();

Режим сохранения путей влияет на то, как получатель увидит содержимое архива:

  • НеСохранятьПути — все файлы попадают в корень архива, структура каталогов теряется;
  • СохранятьОтносительныеПути — сохраняется структура подкаталогов относительно добавляемого каталога;
  • СохранятьПолныеПути — в архиве воспроизводится полный путь на диске, включая диск и все родительские папки.

Для добавления всего содержимого каталога с маской удобно сочетать НайтиФайлы() с циклом по найденным файлам. Это даёт контроль над тем, какие файлы попадут в архив, и позволяет исключить служебные или временные файлы.

Степень сжатия, пароль и шифрование

При добавлении файла можно управлять параметрами сжатия через параметры метода Добавить() или через свойства объекта. Уровень сжатия задаётся перечислением УровеньСжатияZIP: Минимальный, Оптимальный или Максимальный. Для уже сжатых форматов (jpg, mp4, xlsx, docx) высокий уровень почти не даёт выигрыша, но замедляет работу.

Для защиты архива паролем используется свойство Пароль объекта записи и параметр метода Добавить() с методом шифрования МетодШифрованияZIP.AES256 или устаревшим Zip20. Пример:

ЗаписьZIP = Новый ЗаписьZipФайла();

ЗаписьZIP.Открыть("C:\Temp\Секретный.zip", "Пароль123");

ЗаписьZIP.Добавить("C:\Temp\Данные.xml", , , , МетодШифрованияZIP.AES256);

ЗаписьZIP.Записать();

Учтите ограничение совместимости: шифрование AES понимают не все внешние программы. Старые версии встроенного распаковщика Windows могут не открыть такой архив, тогда как шифрование ZipCrypto (Zip20) открывается шире, но считается криптографически слабым и легко взламывается. Для действительно конфиденциальных данных ZIP-пароль — лишь минимальная мера.

Распаковка ZIP-архива в 1С

Обратная операция выполняется объектом ЧтениеZipФайла. Можно извлечь весь архив целиком или выборочные элементы.

ЧтениеZIP = Новый ЧтениеZipФайла("C:\Temp\Архив.zip");

ЧтениеZIP.ИзвлечьВсе("C:\Temp\Распаковка\", РежимВосстановленияПутейФайловZIP.Восстанавливать);

ЧтениеZIP.Закрыть();

Для точечной работы коллекция ЧтениеZIP.Элементы позволяет перебрать содержимое, прочитать имена файлов, их размеры и извлечь только нужное. Если архив защищён паролем, он передаётся в конструктор: Новый ЧтениеZipФайла(ИмяФайла, "Пароль").

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

Контрольные точки

Как проверить результат

Файл архива создан
Норма

Файл существует, размер больше нуля

Тревожный признак

Файл отсутствует или имеет размер 0 байт

Архив открывается
Норма

Проводник или архиватор показывает список файлов

Тревожный признак

Ошибка «архив повреждён» при открытии

Структура путей
Норма

Файлы лежат в ожидаемых папках внутри архива

Тревожный признак

Все файлы в корне или лишние уровни каталогов

Работа с архивом в памяти и передача через хранилище

Частый сценарий в клиент-серверном режиме: архив формируется на сервере, а скачать его нужно на клиенте. Для этого архив записывается во временное хранилище через потоки или через временный файл, после чего передаётся адрес хранилища.

ИмяВременногоФайла = ПолучитьИмяВременногоФайла("zip");

ЗаписьZIP = Новый ЗаписьZipФайла(ИмяВременногоФайла);

ЗаписьZIP.Добавить(ПутьКФайлу);

ЗаписьZIP.Записать();

ДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);

АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификаторФормы);

УдалитьФайлы(ИмяВременногоФайла);

На клиенте остаётся вызвать ПолучитьИзВременногоХранилища() и сохранить данные через диалог выбора файла или метод Записать() двоичных данных. Не забывайте удалять временные файлы: в регламентных заданиях с большой частотой их накопление приводит к переполнению диска сервера.

Порядок действий
  1. 1
    Определите, где формируется архив: на клиенте или на сервере
  2. 2
    Создайте объект ЗаписьZipФайла с путём к будущему архиву
  3. 3
    Добавьте файлы методом Добавить() с нужным режимом путей
  4. 4
    Вызовите Записать() и проверьте наличие файла
  5. 5
    При передаче на клиент поместите архив во временное хранилище
  6. 6
    Удалите временные файлы после использования

Ограничения платформы и типичные ошибки

Встроенный механизм ZIP в 1С покрывает большинство задач, но имеет границы. Многотомные архивы, самораспаковывающиеся архивы (SFX) и форматы 7z/RAR не поддерживаются — только классический ZIP. Для других форматов потребуется вызов внешнего архиватора через командную строку, что в файловом режиме на клиенте несложно, а на сервере потребует настройки прав.

Наиболее частые проблемы на практике:

  • ошибка «Файл не обнаружен» — путь к добавляемому файлу указан относительно клиента, а код выполняется на сервере, где такого пути нет;
  • пустой архив — забыт вызов Записать() или исключение произошло до него;
  • нет доступа — у пользователя, от имени которого работает сервер 1С (обычно USR1CV8), нет прав на целевой каталог;
  • кириллические имена файлов отображаются некорректно при открытии архива в старых программах — используйте актуальную версию платформы, где корректно записывается кодировка имён.

Для диагностики проблем с правами сначала проверьте запись в каталог временных файлов сервера: если туда архив создаётся, а в сетевую папку — нет, проблема точно в правах учётной записи службы сервера 1С, а не в коде.

Типичные ошибки
01
Вызов Добавить() с клиентским путём в серверном коде — файл не найден, так как на сервере нет диска C пользователя
02
Пропуск Записать() — архив не создаётся, ошибок при этом платформа не выдаёт
03
Накопление временных файлов в каталоге Temp сервера из-за отсутствия УдалитьФайлы()
04
Использование слабого шифрования Zip20 для конфиденциальных данных с расчётом на надёжную защиту

Когда ZIP встроенными средствами не подходит

Если требуется максимальная степень сжатия, формат 7z, разбиение на тома или интеграция с уже настроенным корпоративным архиватором, имеет смысл вызывать внешнюю программу через КомандаСистемы() или ЗапуститьПриложение(). Например, консольная версия 7-Zip управляется параметрами командной строки и легко встраивается в регламентные задания.

Минус подхода — зависимость от установленного ПО на сервере, права на запуск приложений и необходимость анализировать код возврата. Для типовых задач (отправка выгрузок, пакеты документов, обмен с контрагентами) встроенного ЗаписьZipФайла достаточно, и это более переносимое решение.

Сравнение вариантов

ЗаписьZipФайла (встроенный)

Подходит для большинства задач, работает везде без установки ПО; ограничение — только формат ZIP

Внешний архиватор (7-Zip и др.)

Нужны тома, 7z/RAR или особые параметры; требует установки на сервере и прав на запуск

Отправка без сжатия

Допустимо для одного небольшого файла; для пакетов документов увеличивает трафик и риск потери части файлов

Итог

Что важно запомнить

Сжатие в ZIP в 1С выполняется объектом ЗаписьZipФайла: Открыть/конструктор → Добавить() → Записать(). Следите за режимом сохранения путей, правами серверной учётной записи и обязательно удаляйте временные файлы.

Частые вопросы

Можно ли сжать файл в ZIP в 1С без сохранения на диск?

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

Почему архив создаётся пустым или не создаётся вовсе?

Чаще всего не вызван метод Записать() — без него файл физически не появляется. Вторая причина — исключение в коде между добавлением файлов и записью. Оберните логику в попытку и проверяйте наличие файла после записи.

Как добавить в архив файлы только определённого типа?

Используйте НайтиФайлы(Каталог, "*.xml", Истина) — третий параметр включает поиск в подкаталогах. Затем в цикле добавьте каждый найденный файл методом Добавить(). Так можно фильтровать по нескольким маскам и исключать лишнее.

Откроет ли получатель архив с паролем AES, созданный в 1С?

Современные версии 7-Zip и WinRAR открывают AES-архивы без проблем. Встроенный распаковщик старых версий Windows может не справиться. Если заранее неизвестно, чем будет открывать архив получатель, протестируйте совместимость или используйте Zip20 с пониманием его слабости.

Есть ли ограничение на размер файлов при сжатии в 1С?

Жёсткого ограничения в самом объекте нет, но на практике упираются в доступную память и дисковое пространство, особенно при работе через временные файлы и хранилище. Для очень больших наборов данных архив лучше формировать порциями и контролировать свободное место на сервере.

Как узнать содержимое архива, не распаковывая его?

Создайте ЧтениеZipФайла и переберите коллекцию Элементы: у каждого элемента доступны имя, исходный и сжатый размер, время изменения. Это позволяет проверить состав архива перед извлечением и отказаться от распаковки подозрительного содержимого.