Распаковка ZIP-архива кодом 1С:Предприятия 8.3 — ЧтениеZipФайла, папки, ошибки

· 9 мин

Содержание

Распаковать ZIP файл в 1С можно без внешних программ: в платформе 8.3 есть объект ЧтениеZipФайла. Открываете архив, вызываете ИзвлечьВсе() с каталогом назначения, закрываете архив — три строки кода. Код выполняют на сервере или в толстом клиенте.

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

Тема общая для платформы и не зависит от конфигурации: код одинаково работает в БП 3.0, ЗУП 3.1, УТ 11 и любой другой базе на 8.3.

Что проверить перед распаковкой архива в 1С

Большая часть проблем с распаковкой — не в коде, а в окружении. Проверьте четыре вещи до того, как писать обработку.

  • 🖥️ Где выполняется код. В клиент-серверной базе серверный код работает на компьютере с сервером 1С. Путь C:\Обмен\выгрузка.zip должен существовать именно там, а не на ПК бухгалтера.
  • 🔑 От чьего имени работает сервер. Рабочие процессы сервера 1С запускаются от учётной записи службы (по умолчанию USR1CV8). Этой учётной записи нужны права на чтение архива и на запись в каталог назначения.
  • 🌐 Сетевые папки. Путь вида \\server\share\ служба видит, только если у её учётной записи есть доступ к шаре. Буквы сетевых дисков (Z:\) служба не видит вовсе — используйте UNC-путь.
  • 🛡️ Безопасный режим. Внешняя обработка, подключённая в безопасном режиме, не получает доступа к файловой системе. Если в базе включены профили безопасности, обработке нужно разрешение на использование внешних ресурсов.

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

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

Как распаковать ZIP-архив встроенным объектом ЧтениеZipФайла

Минимальный пример. Процедура распаковывает весь архив в указанный каталог с сохранением вложенных папок:

&НаСервере
Процедура РаспаковатьАрхив(ПутьКАрхиву, КаталогНазначения)

	Архив = Новый ЧтениеZipФайла(ПутьКАрхиву);
	Архив.ИзвлечьВсе(КаталогНазначения, РежимВосстановленияПутейФайловZIP.Восстанавливать);
	Архив.Закрыть();

КонецПроцедуры

Что здесь происходит:

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

Архив с паролем

Пароль передают вторым параметром конструктора:

Архив = Новый ЧтениеZipФайла(ПутьКАрхиву, "Пароль123");

Если пароль подходит не ко всем файлам, у метода Извлечь() есть свой параметр пароля для отдельного элемента. Проверить, зашифрован ли элемент, можно по его свойству Зашифрован.

Что можно узнать об архиве до распаковки

Коллекция Архив.Элементы содержит описания всех файлов. У каждого элемента есть полезные свойства:

СвойствоЧто содержит
Имяимя файла без пути
ПолноеИмяпуть внутри архива с именем файла
Путьпуть внутри архива без имени
НесжатыйРазмерразмер файла после распаковки, в байтах
Размерразмер в сжатом виде
ЗашифрованИстина, если файл защищён паролем

По НесжатыйРазмер удобно заранее проверить, хватит ли места на диске: архив на 50 МБ с текстовыми выгрузками легко разворачивается в 500 МБ.

Распаковка ZIP с вложенными папками: целиком или выборочно

Режим восстановления путей решает, как файлы лягут на диск.

РежимРезультатКогда подходит
Восстанавливатьструктура папок архива повторяется в каталоге назначениявыгрузки с иерархией, архивы обменов
НеВосстанавливатьвсе файлы складываются в один каталогнужны только файлы, папки не важны

В режиме НеВосстанавливать файлы с одинаковыми именами из разных папок перезапишут друг друга. Если в архиве 2026-09\report.xml и 2026-10\report.xml, на диске останется один.

Извлечь только нужные файлы

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

&НаСервере
Функция ИзвлечьXML(ПутьКАрхиву, КаталогНазначения)

	Извлечено = Новый Массив;
	Архив = Новый ЧтениеZipФайла(ПутьКАрхиву);

	Для Каждого Элемент Из Архив.Элементы Цикл

		// защита от путей, уводящих за пределы каталога
		Если СтрНайти(Элемент.ПолноеИмя, "..") > 0 Тогда
			Продолжить;
		КонецЕсли;

		Если Не СтрЗаканчиваетсяНа(НРег(Элемент.Имя), ".xml") Тогда
			Продолжить;
		КонецЕсли;

		Архив.Извлечь(Элемент, КаталогНазначения,
			РежимВосстановленияПутейФайловZIP.Восстанавливать);
		Извлечено.Добавить(КаталогНазначения + Элемент.ПолноеИмя);

	КонецЦикла;

	Архив.Закрыть();
	Возврат Извлечено;

КонецФункции

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

Найти файлы после распаковки

Когда архив распакован целиком, файлы удобнее искать функцией НайтиФайлы() с рекурсивным обходом:

Файлы = НайтиФайлы(КаталогНазначения, "*.xml", Истина);
Для Каждого Файл Из Файлы Цикл
	// Файл.ПолноеИмя — путь на диске, можно читать
КонецЦикла;

Третий параметр Истина включает поиск во всех подкаталогах.

Распаковать архив, который загрузил пользователь

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

Шаг 1. Передать файл на сервер

В модуле формы, на клиенте:

&НаКлиенте
Процедура ЗагрузитьАрхив(Команда)
	Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
	НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
	Если Результат Тогда
		РаспаковатьИзХранилища(Адрес);
	КонецЕсли;
КонецПроцедуры

Шаг 2. Записать во временный файл и распаковать

&НаСервере
Процедура РаспаковатьИзХранилища(Адрес)

	ДанныеАрхива = ПолучитьИзВременногоХранилища(Адрес);
	ИмяАрхива = ПолучитьИмяВременногоФайла("zip");
	ДанныеАрхива.Записать(ИмяАрхива);

	Каталог = КаталогВременныхФайлов()
		+ Строка(Новый УникальныйИдентификатор) + ПолучитьРазделительПути();
	СоздатьКаталог(Каталог);

	Архив = Новый ЧтениеZipФайла(ИмяАрхива);
	Архив.ИзвлечьВсе(Каталог, РежимВосстановленияПутейФайловZIP.Восстанавливать);
	Архив.Закрыть();

	// ... обработка файлов из Каталог ...

	УдалитьФайлы(ИмяАрхива);
	УдалитьФайлы(Каталог);

КонецПроцедуры

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

Не забывайте удалять временные файлы. Без УдалитьФайлы() каталог временных файлов сервера за несколько месяцев обменов разрастается на гигабайты.

Ошибки при распаковке ZIP в 1С и защита от сбоев

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

&НаСервере
Функция РаспаковатьБезопасно(ПутьКАрхиву, Каталог, Пароль = "")

	Архив = Неопределено;
	Попытка
		Архив = Новый ЧтениеZipФайла(ПутьКАрхиву, Пароль);
		Архив.ИзвлечьВсе(Каталог, РежимВосстановленияПутейФайловZIP.Восстанавливать);
		Архив.Закрыть();
		Возврат Истина;
	Исключение
		Если Архив <> Неопределено Тогда
			Попытка
				Архив.Закрыть();
			Исключение
			КонецПопытки;
		КонецЕсли;
		ЗаписьЖурналаРегистрации("Распаковка ZIP",
			УровеньЖурналаРегистрации.Ошибка, , ПутьКАрхиву,
			ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Возврат Ложь;
	КонецПопытки;

КонецФункции

Текст ошибки окажется в журнале регистрации: Администрирование → Обслуживание → Журнал регистрации, отбор по событию «Распаковка ZIP».

Что обычно ломается

Диагностика: выберите симптом

Проверки, которые стоит встроить в код

  • 📏 Размер. Сложите НесжатыйРазмер всех элементов и сравните с разумным пределом. Это защищает от архивов-«бомб», которые разворачиваются в десятки гигабайт.
  • 🚫 Пути с ... Пропускайте такие элементы, как в примере выше. Иначе файл из чужого архива может записаться за пределами каталога назначения.
  • 🧹 Очистка. Удаляйте временные файлы и при ошибке тоже, а не только после успешной загрузки.

Автоматическая распаковка архивов: внешняя обработка и регламентное задание

Когда архивы приходят каждый день в одну папку, распаковку и загрузку стоит поручить расписанию.

Вариант 1. Дополнительная обработка с расписанием

В типовых конфигурациях на БСП (БП 3.0, ЗУП 3.1, УТ 11) внешнюю обработку можно подключить как дополнительную и запускать по расписанию:

  1. Оформите обработку как дополнительную: в модуле объекта нужна экспортная функция СведенияОВнешнейОбработке() и команда с типом вызова серверного метода.
  2. Подключите её: Администрирование → Печатные формы, отчеты и обработки → Дополнительные отчеты и обработки.
  3. В карточке обработки, на строке команды, задайте расписание.
  4. Включите публикацию и сохраните карточку.

Серверный метод обработки обходит папку обмена, распаковывает каждый архив, загружает данные и переносит обработанный ZIP в подпапку Архив, чтобы не загрузить его повторно.

Вариант 2. Регламентное задание в расширении

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

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

Как не загрузить один архив дважды

  • 📁 Переносите обработанный файл в отдельную папку через ПереместитьФайл().
  • 🧾 Или храните имена загруженных архивов в регистре сведений и проверяйте перед распаковкой.
  • 🔁 Если архив не распаковался, переносите его в папку Ошибки, а не оставляйте на месте: иначе задание будет падать на нём каждый запуск.

Встроенные средства 1С или 7-Zip: что выбрать

ЧтениеZipФайла закрывает почти все задачи с ZIP. Внешняя утилита нужна, когда формат другой или нужна функция, которой нет в платформе.

СпособКогда подходитОграничения
ЧтениеZipФайлаобычные ZIP-архивы, обмены, выгрузкитолько формат ZIP
7-Zip через ЗапуститьПриложение()RAR, 7z, многотомные архивыутилиту ставят на каждый сервер, нужен контроль кода возврата
PowerShell Expand-ArchiveZIP на Windows-сервере без установки утилиттолько Windows, только ZIP
unzipсервер 1С на Linuxпакет должен быть установлен

Запуск 7-Zip из кода выглядит так:

Команда = """C:\Program Files\7-Zip\7z.exe"" x """ + ПутьКАрхиву
	+ """ -o""" + КаталогНазначения + """ -y";
КодВозврата = 0;
ЗапуститьПриложение(Команда, , Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
	ВызватьИсключение "7-Zip вернул код " + Формат(КодВозврата, "ЧГ=0");
КонецЕсли;

Ключ x распаковывает с сохранением папок, -o задаёт каталог (без пробела после ключа), -y отвечает «да» на вопросы о перезаписи. Третий параметр Истина заставляет 1С дождаться окончания распаковки.

Внешнюю утилиту берите только тогда, когда без неё никак. Каждая такая зависимость — лишняя настройка при переезде на новый сервер, и о ней часто забывают.

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

Можно ли распаковать ZIP в веб-клиенте 1С?
Нет, объект ЧтениеZipФайла в веб-клиенте недоступен. Передайте файл на сервер через временное хранилище и распакуйте там.
Как прочитать файл из архива, не сохраняя его на диск?
Распакуйте его во временный каталог, прочитайте нужным объектом (ЧтениеXML, ЧтениеТекста, ДвоичныеДанные) и сразу удалите. Так надёжнее и проще в отладке.
Как узнать список файлов в архиве без распаковки?
Откройте архив через ЧтениеZipФайла и переберите коллекцию Элементы. Файлы при этом на диск не пишутся.
Как упаковать файлы обратно в ZIP?
Для этого есть парный объект ЗаписьZipФайла: методы Добавить() и Записать(). Он же умеет ставить пароль и выбирать уровень сжатия.
Почему из Конфигуратора распаковка работает, а у пользователей — нет?
Чаще всего разные права: у разработчика есть доступ к папке, а у учётной записи службы сервера или у пользователя — нет. Проверьте права на каталог от имени той учётной записи, под которой выполняется код.