Пошаговые инструкции Для начинающих 14 мин

ZIP в n8n: как создать архив, распаковать и проверить файлы

Упакуйте CSV, TXT и JSON в один ZIP, распакуйте и сравните файлы с оригиналом. 12 шагов, готовый workflow и проверки ошибок.

n8n ZIP Binary

Три файла в n8n не обязательно означают три items. Несколько файлов могут лежать в разных binary-полях одного item — именно такой пакет удобно упаковать в один ZIP. Соберём его из учебных CSV, TXT и JSON, распакуем и сравним содержимое с оригиналом байт в байт.

Результат инструкции

Получим ezgpt-demo.zip с orders.csv, readme.txt и metadata.json. Первый Compression создаст архив, второй распакует его. Финальная проверка вернёт один JSON с file_count 3 и roundtrip_ok true, только если сохранились все имена и все байты. AI-модель и внешние сервисы для этого не нужны.

Работаем только с вымышленными данными. Схема не отправляет архив и не записывает его в ваши рабочие папки. n8n хранит binary-данные в своём хранилище выполнений; при файловом режиме оно находится на диске сервера n8n. Для скачивания готового ZIP нужно открыть выход Make ZIP, а не искать архив в итоговом JSON.

Что понадобится

  • Работающий n8n и права создать отдельный учебный workflow. Проверено на n8n 2.42.4, Compression версии 1.1.
  • Доступ к Code на JavaScript. Учебные файлы создаются прямо в схеме, без чтения папок компьютера и без API-ключей.
  • Отдельное тестовое выполнение. Сюда не нужно загружать договоры, клиентские базы и неизвестные архивы из почты.

Установить n8n локально через Docker

Шаг 1. Импортируйте готовый workflow

Скачать n8n-zip-roundtrip.json

Создайте новый workflow. В меню редактора выберите Import from File и загрузите JSON. После импорта должно быть семь узлов:

text
Manual Trigger → Sample Files → Check Files → Make ZIP
→ Check ZIP → Open ZIP → Check Roundtrip

Make ZIP и Open ZIP — штатный Compression. Sample Files, Check Files, Check ZIP и Check Roundtrip — Code. Схема неактивна, credentials и ID чужого workflow в файле нет. При ручной сборке сохраните эти имена: последний Code получает эталон из Check Files.

Шаг 2. Разделите понятия поля и файла

В примере один item содержит три binary-поля: orders, readme и meta. Внутри них лежат файлы orders.csv, readme.txt и metadata.json. В настройку Input Binary Field(s) вводятся имена полей через запятую, а не имена файлов и не путь к папке.

Например, orders — имя binary-поля, orders.csv — значение его metadata.fileName, а 001 — ID заказа внутри CSV. Эти три имени решают разные задачи. Файлы не должны называться одинаково: при упаковке одинаковые имена могут привести к потере одного из содержимых, поэтому проверим их заранее.

Скачать пример ZIP, созданный проверенным workflow

Готовый архив нужен только как образец. Для выполнения инструкции он не требуется: ваши три файла создаст следующий Code. Образец содержит только вымышленные записи и отдельно проверен после создания.

Шаг 3. Создайте три учебных файла

В Sample Files выберите Mode: Run Once for All Items, Language: JavaScript. Вставьте весь код:

javascript
const files = [
  {
    "field": "orders",
    "name": "orders.csv",
    "mime": "text/csv",
    "text": "order_id,client,amount_minor\n001,Альфа,150000\n002,Бета,0\n"
  },
  {
    "field": "readme",
    "name": "readme.txt",
    "mime": "text/plain",
    "text": "Учебный архив ezGPT. Только вымышленные данные.\n"
  },
  {
    "field": "meta",
    "name": "metadata.json",
    "mime": "application/json",
    "text": "{\"batch_id\":\"zip-demo-001\",\"currency\":\"RUB\"}\n"
  }
];
const binary = {};
for (const file of files) {
  binary[file.field] = await this.helpers.prepareBinaryData(
    Buffer.from(file.text, 'utf8'), file.name, file.mime,
  );
}
return [{ json: { batch_id: 'zip-demo-001' }, binary }];

Выполните workflow от Manual Trigger. В Output Sample Files ожидается один item. Во вкладке Binary должны быть orders, readme и meta, а не JSON-строки с такими именами. prepareBinaryData создаёт файловые данные и метаданные; Buffer.from кодирует исходный текст в UTF-8.

orders.csv содержит два вымышленных заказа. Его текст:

csv
order_id,client,amount_minor
001,Альфа,150000
002,Бета,0

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

Шаг 4. Проверьте входные файлы

В Check Files задайте Run Once for All Items, JavaScript и вставьте:

javascript
const items = $input.all();
if (items.length !== 1) throw new Error('one_file_item_required');
const item = items[0];
const binary = item.binary || {};
if (Object.keys(binary).sort().join('|') !== 'meta|orders|readme') {
  throw new Error('binary_fields_mismatch');
}
const names = new Set();
const manifest = [];
const expected = { orders: 'orders.csv', readme: 'readme.txt', meta: 'metadata.json' };
for (const [field, fileName] of Object.entries(expected)) {
  const actualName = binary[field].fileName;
  if (typeof actualName !== 'string' || !actualName || names.has(actualName)) {
    throw new Error('file_name_missing_or_duplicate');
  }
  if (actualName !== fileName) throw new Error('file_name_mismatch');
  names.add(actualName);
  const buffer = await this.helpers.getBinaryDataBuffer(0, field);
  if (!buffer.length || buffer.length > 16384) throw new Error('file_size_invalid');
  const text = buffer.toString('utf8');
  if (!Buffer.from(text, 'utf8').equals(buffer)) throw new Error('file_utf8_invalid');
  manifest.push({ file_name: fileName, bytes: buffer.length, text });
}
return [{ json: { batch_id: item.json.batch_id, manifest }, binary }];

Разрешён ровно один item с тремя нужными binary-полями. Каждое имя файла должно совпадать с ожидаемым, содержимое не должно быть пустым или больше 16384 байт, текст обязан корректно восстанавливаться из UTF-8. Значение 16384 — учебное ограничение отдельного файла, не предел возможностей Compression.

Для чтения файла используется this.helpers.getBinaryDataBuffer, а не поле binary.orders.data. В файловом режиме data может быть служебной ссылкой, а не base64 с содержимым. В JSON сохраняется manifest с именами, длиной и исходным текстом: он нужен для проверки после распаковки. Для больших или конфиденциальных файлов такой текстовый эталон нужно заменить другим подходом и продумать срок хранения выполнений.

В Settings всех узлов оставьте On Error: Stop Workflow. Always Output Data, Continue On Fail, Retry On Fail и Execute Once не включайте. Ошибка имени или пропущенный файл не исправятся повторной упаковкой.

Шаг 5. Создайте ZIP

В Make ZIP выберите Operation: Compress и заполните четыре настройки:

Настройка Значение Что означает
Input Binary Field(s) orders,readme,meta Три поля одного item
Output Format Zip Один ZIP, не три Gzip
File Name ezgpt-demo.zip Имя скачиваемого архива
Put Output File in Field bundle Binary-поле с архивом

Выполните узел. Ожидается один item с binary-полем bundle. Его File Name — ezgpt-demo.zip, File Extension — zip. В проверенном запуске архив занял 507 байт. Не требуйте такой же размер у каждой сборки: важнее содержимое, а ZIP может включать служебные данные и временные метки.

Для маленьких файлов ZIP может оказаться больше суммы исходных файлов из-за заголовков архива. В примере исходные данные занимают 194 байта. Архив здесь нужен для объединения трёх файлов, а не как обещание экономии места.

Шаг 6. Проверьте выход перед распаковкой

В Check ZIP выберите Run Once for All Items, JavaScript и вставьте:

javascript
const items = $input.all();
if (items.length !== 1 || Object.keys(items[0].binary || {}).join('|') !== 'bundle') {
  throw new Error('zip_binary_field_required');
}
const file = items[0].binary.bundle;
if (file.fileName !== 'ezgpt-demo.zip' || file.fileExtension !== 'zip') {
  throw new Error('zip_name_or_extension_invalid');
}
const buffer = await this.helpers.getBinaryDataBuffer(0, 'bundle');
if (buffer.length > 65536 || buffer.subarray(0, 4).toString('hex') !== '504b0304') {
  throw new Error('zip_header_or_size_invalid');
}
return items;

Ожидается только binary-поле bundle с именем ezgpt-demo.zip и расширением zip. Затем проверяются размер до 65536 байт и первые четыре байта ZIP с локальной записью файла. Это узкая проверка нашего непустого архива, не универсальный детектор всех ZIP и не проверка безопасности вложений.

Успех Check ZIP не доказывает, что архив не повреждён: в нём ещё может оказаться сломанная структура. Настоящая распаковка произойдёт в следующем Compression. Не подавайте сюда неизвестные архивы только потому, что их первые байты похожи на ZIP.

Шаг 7. Распакуйте архив

В Open ZIP выберите Operation: Decompress. В Input Binary Field(s) укажите bundle, в Output Prefix — file_. Выполните узел от начала цепочки.

Ожидается один item с тремя binary-полями file_0, file_1 и file_2. Это не три items. В проверенном примере они содержат orders.csv, readme.txt и metadata.json соответственно. Но дальнейшую логику не стоит связывать только с номером поля: она будет искать нужное имя файла.

File Name Размер UTF-8 Что внутри
orders.csv 66 байт Два вымышленных заказа
readme.txt 83 байта Учебное пояснение
metadata.json 45 байт ID пакета и валюта

После распаковки исходное имя orders.csv остаётся в fileName, хотя binary-поле уже называется file_0. Если поменять Output Prefix на unpacked_, изменятся поля, но не имена файлов. Нашу итоговую проверку это не должно сломать.

Шаг 8. Сравните результат с оригиналом

В Check Roundtrip задайте Run Once for All Items, JavaScript и вставьте:

javascript
const items = $input.all();
if (items.length !== 1) throw new Error('one_unpacked_item_required');
const binary = items[0].binary || {};
const expected = $('Check Files').first().json.manifest;
if (Object.keys(binary).length !== expected.length) throw new Error('unpacked_count_mismatch');
const found = new Set();
const files = [];
for (const [field, metadata] of Object.entries(binary)) {
  const original = expected.find(file => file.file_name === metadata.fileName);
  if (!original || found.has(metadata.fileName)) throw new Error('unpacked_name_mismatch');
  const buffer = await this.helpers.getBinaryDataBuffer(0, field);
  if (!buffer.equals(Buffer.from(original.text, 'utf8'))) throw new Error('unpacked_content_mismatch');
  found.add(metadata.fileName);
  files.push({ file_name: metadata.fileName, bytes: buffer.length, matches_original: true });
}
files.sort((a, b) => a.file_name.localeCompare(b.file_name));
return [{ json: {
  batch_id: $('Check Files').first().json.batch_id,
  archive_name: 'ezgpt-demo.zip',
  file_count: files.length,
  files,
  roundtrip_ok: true,
  action_performed: false,
} }];

Проверяются количество распакованных файлов, точные имена без повторов и полное совпадение каждого буфера с исходным UTF-8-текстом из Check Files. Это сильнее проверки только размера: два разных текста могут занимать одинаковое число байт. Порядок binary-полей не важен.

Финальный files сортируется по имени только ради удобного вывода. matches_original true означает совпадение с эталоном данного выполнения. Если перед запуском вы сами измените учебный текст, эталон тоже изменится. Это контроль упаковки и распаковки, не доказательство правильности или подлинности исходного документа.

Шаг 9. Выполните всю схему

Нажмите Execute Workflow. Каждый узел должен обработать один item. Последний вернёт такой JSON:

json
{
  "batch_id": "zip-demo-001",
  "archive_name": "ezgpt-demo.zip",
  "file_count": 3,
  "files": [
    {
      "file_name": "metadata.json",
      "bytes": 45,
      "matches_original": true
    },
    {
      "file_name": "orders.csv",
      "bytes": 66,
      "matches_original": true
    },
    {
      "file_name": "readme.txt",
      "bytes": 83,
      "matches_original": true
    }
  ],
  "roundtrip_ok": true,
  "action_performed": false
}

Проверьте file_count 3, roundtrip_ok true и три matches_original true. action_performed false означает, что схема не отправляла файлы и не записывала их в ваши рабочие папки. Создание файлов и архива внутри хранилища n8n при этом действительно происходило.

Чтобы получить сам архив, откройте выход Make ZIP, переключитесь на Binary и скачайте bundle средствами интерфейса. В Check Roundtrip бинарные файлы намеренно не переносятся: там только отчёт. Наличие отчёта не означает, что архив отправлен клиенту или загружен в облако.

Шаг 10. Проверьте отсутствие файла и неверное имя

В Make ZIP временно уберите meta из Input Binary Field(s), оставив orders,readme. Полный запуск должен дойти до Check Roundtrip и остановиться с unpacked_count_mismatch: архив создан, но в него попали только два файла. Верните orders,readme,meta.

Теперь в Sample Files временно замените у записи metadata.json значение name на readme.txt. Check Files должен остановиться с file_name_missing_or_duplicate ещё до упаковки. Верните metadata.json. Так проверяется, что одинаковое имя не приводит к незаметной потере содержимого.

Если вместо списка binary-полей указать в Make ZIP поле data, ошибка должна возникнуть в самом Make ZIP: такого входного поля в схеме нет. Не переименовывайте всё подряд ради устранения ошибки; сверяйте именно binary-поля предыдущего узла.

Шаг 11. Проверьте независимость от номера поля

В Open ZIP временно замените Output Prefix file_ на unpacked_. После полного запуска итог должен совпасть с шагом 9. Check Roundtrip читает все binary-поля и сопоставляет их по fileName, поэтому не зависит от префикса. После теста верните file_.

Можно также изменить текст readme.txt в Sample Files, сохранив его имя. Схема должна успешно обработать новый текст, а число bytes для readme.txt изменится. Это ожидаемо: эталон создаётся из текущего входа до Make ZIP. Для точного результата из примера верните исходную строку вместе с завершающим переносом.

Шаг 12. Восстановите и сохраните рабочий вариант

Верните три исходных файла, Input Binary Field(s) orders,readme,meta, формат Zip, имя ezgpt-demo.zip, выход bundle и префикс file_. Сохраните workflow и выполните его ещё раз. Сверьте не только зелёный статус, но и имена, длины, количество и roundtrip_ok.

Если дальше нужен разбор orders.csv, выбирайте распакованный файл по fileName и передавайте его в Extract from File. Не считайте все вложения CSV и не исполняйте их содержимое. Отправку архива, загрузку в облако и запись в рабочую папку добавляют отдельным действием после проверки.

Если результат отличается

Ошибка Что произошло Где проверить
binary_fields_mismatch Нет нужного binary-поля или появилось лишнее Выход Sample Files
file_name_missing_or_duplicate Имя отсутствует или повторяется name в исходных files
zip_binary_field_required На выходе не только bundle Формат и выход Make ZIP
unpacked_count_mismatch Распакованы не все три файла Список входных полей Make ZIP
unpacked_content_mismatch Байты отличаются от эталона Узлы между Open ZIP и проверкой

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

Что нельзя доверять этой схеме без доработки

Этот workflow проверяет собственный маленький архив с тремя известными текстовыми файлами. Он не сканирует вложения антивирусом, не проверяет подписи, не работает с паролями и не доказывает безопасность чужих ZIP. Нельзя распаковывать неизвестные архивы в рабочую папку или автоматически открывать и запускать вложенные файлы.

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

Несколько входных items не объединяются здесь в один общий архив. Пример сознательно требует один item с тремя binary-полями. Другие режимы хранения binary, распределённые workers, большие архивы и n8n Cloud требуют отдельного прогона.

Прочитать CSV через Extract from File

Выгрузить данные n8n в CSV и проверить файл

Остановить workflow при неверных данных

Что проверено редакцией

16 октября 2026 года workflow проверен на n8n 2.42.4 в отдельном Docker-экземпляре с binary-режимом filesystem через ручные запуски API. Все 27 тестов прошли: основной roundtrip, другой порядок binary-полей, изменённый текст, другой префикс распаковки, экспорт ZIP, отсутствующее/лишнее binary-поле, только JSON, два items, повтор/отсутствие/неверное имя, пустой/слишком большой/невалидный UTF-8 файл, неверное поле упаковки, пропуск файла в архиве, другое выходное поле, имя и формат, неверный заголовок/слишком большой ZIP/нет расширения, неверное поле распаковки, повреждённый ZIP, изменение имени и байтов после распаковки. Основной запуск использует точный скачиваемый workflow без подмены кода. Сверены manifest, точные имена и длины, UTF-8, совпадение байтов и отсутствие успешного отчёта при ошибках. Образец ZIP отдельно прочитан стандартной библиотекой Windows: три файла совпадают с исходными байтами. Настройки Compression 1.1 и binary helper сверены с официальной документацией и кодом узла. Редакторские клики и кнопка скачивания, Cloud, другие binary-режимы, большие/защищённые паролем/чужие архивы, другие форматы и полный аудит безопасности не тестировались. Учебный контейнер остановлен, существующие workflows не менялись. Обложка — редакционная AI-иллюстрация.

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

Что вводить в Input Binary Field(s): orders или orders.csv?

Имя binary-поля, в этом примере orders. Имя файла orders.csv хранится в его метаданных. Для трёх файлов введите orders,readme,meta.

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

Compression в проверенном сценарии кладёт распакованные файлы в разные binary-поля одного item. Их имена начинаются с Output Prefix. Число items не равно числу файлов.

Где скачать ZIP, если в конце только JSON?

Откройте выход Make ZIP и его binary-поле bundle. Check Roundtrip специально возвращает только отчёт о проверке, а не сам архив.

Почему ZIP больше исходных файлов?

У архива есть заголовки и другая служебная информация. Для нескольких очень маленьких файлов она может перевесить экономию от сжатия. Объединение файлов не гарантирует уменьшение размера.

Можно распаковывать архивы клиентов по этой инструкции?

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

Дальше по теме

Похожие материалы