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

Как прочитать ICS-файл в n8n и получить данные встречи

Извлеките событие из ICS через Extract from File. 10 шагов, готовый workflow, учебный календарь и проверка названия, UID, времени UTC и длительности.

n8n JSON ICS

Файл .ics содержит событие календаря, но для автоматизации обычно нужны отдельные поля: название, время начала, окончание и UID. Прочитаем учебный ICS в n8n штатным Extract from File и получим проверенный JSON. Подключать календарный API или вручную разбирать строки файла не потребуется.

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

Получим одну «Учебную встречу» на 20 октября 2026 года, с 10:00 до 10:30 UTC. В результате будут UID, название, описание, место и длительность 30 минут. Исходный файл останется в binary.document, чтобы его можно было сравнить с извлечёнными данными.

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

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

  • Отдельный новый workflow в n8n. Проверено на n8n 2.42.4, HTTP Request 4.4, Extract from File 1.1 и Code 2.
  • Доступ n8n к учебному HTTPS-файлу ezgpt.ru. В нём вымышленные данные, без настоящих участников.
  • Для сравнения — текстовый редактор. Импортировать образец в личный или рабочий календарь не нужно.

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

Шаг 1. Откройте учебный ICS как текст

Скачать n8n-meeting-demo.ics

Скачайте файл и откройте его текстовым редактором. Не используйте двойной щелчок, если .ics автоматически открывается вашим календарём: для этого задания импорт не нужен.

Внутри должны быть BEGIN:VCALENDAR, один BEGIN:VEVENT и поля SUMMARY, DTSTART, DTEND и UID. Начало записано как DTSTART:20261020T100000Z, конец — DTEND:20261020T103000Z. Буква Z обозначает UTC. Описание находится в DESCRIPTION, место — в LOCATION.

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

Как создать такой ICS-файл в n8n

Шаг 2. Импортируйте workflow

Скачать n8n-read-ics-event.json

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

text
Manual Trigger → Download ICS → Check File → Read ICS → Check Event

Download ICS — HTTP Request, Read ICS — Extract from File. Check File и Check Event — Code, JavaScript, Run Once for All Items. Вся цепочка работает с учебным файлом, существующие workflows менять не нужно.

Шаг 3. Настройте загрузку файла

В Download ICS выберите GET и Authentication: None. URL — https://ezgpt.ru/storage/article-files/n8n-meeting-demo.ics. В Options добавьте Response и проверьте:

Поле HTTP Request Значение Для чего
Response Format File Получить binary, не строку ответа
Put Output in Field document Назвать входной файл
Include Response Headers and Status Включено Проверить код и тип ответа
Never Error Выключено Не считать HTTP-ошибку успехом

В Redirects выключите Follow Redirects. Timeout установите 15000 мс, Ignore SSL Issues оставьте выключенным. Для известного учебного URL переход на страницу входа не должен незаметно заменить файл. Если источник другой, его доступ и правила перенаправлений проверяют отдельно.

Учебный сервер сейчас отдаёт этот .ics как application/octet-stream. Поэтому проверка разрешает для данного сценария два MIME: text/calendar и application/octet-stream. Сам по себе ни один из них не доказывает корректность ICS: дальше проверяются байты и выполняется настоящий разбор.

Шаг 4. Проверьте скачанный файл

В Check File вставьте:

javascript
const items = $input.all();
if (items.length !== 1) throw new Error('one_download_required');
const item = items[0];
const type = String(item.json.headers?.['content-type'] ?? '').split(';')[0].trim().toLowerCase();
if (item.json.statusCode !== 200 || !['text/calendar', 'application/octet-stream'].includes(type)) {
  throw new Error('calendar_http_response_required');
}
if (Object.keys(item.binary ?? {}).join('|') !== 'document') throw new Error('document_required');
const bytes = await this.helpers.getBinaryDataBuffer(0, 'document');
if (bytes.length < 1 || bytes.length > 8192) throw new Error('calendar_size_invalid');
const text = bytes.toString('utf8');
if (!Buffer.from(text, 'utf8').equals(bytes) || text.includes('\u0000')) throw new Error('calendar_utf8_invalid');
const readable = text.charCodeAt(0) === 0xFEFF ? text.slice(1) : text;
if (!readable.startsWith('BEGIN:VCALENDAR') || !readable.trimEnd().endsWith('END:VCALENDAR')) {
  throw new Error('calendar_wrapper_required');
}
return [{ json: { source_bytes: bytes.length }, binary: item.binary }];

Код требует HTTP 200 и один файл в document. Размер ограничен 8192 байтами, текст должен быть корректным UTF-8 без NUL и иметь внешние границы VCALENDAR. При наличии UTF-8 BOM он учитывается только для этой предварительной проверки; исходные байты сохраняются.

Это первичная проверка, не самостоятельный парсер и не антивирус. HTML-страница с расширением .ics не должна пройти дальше только из-за имени. Структуру календаря разбирает следующий штатный узел. Размер проверяется уже после загрузки и не заменяет ограничение входящего трафика на сервере.

Шаг 5. Прочитайте календарь через Extract from File

В Read ICS выберите следующие параметры:

Параметр Значение Результат
Operation Extract From ICS Разобрать iCalendar
Input Binary Field document Прочитать скачанный файл
Destination Output Field calendar Сохранить календарь в JSON
Keep Source в Options Both Оставить JSON-метаданные и исходный binary

File Encoding установите utf8, Strip BOM включите. Не выбирайте Extract From Text File: он вернёт текст файла, а не объект с событиями. Поле calendar находится в JSON, а document остаётся в Binary. Это разные пространства данных.

В проверенной версии нативная операция использует библиотеку ts-ics. В этой инструкции нет регулярных выражений для извлечения SUMMARY или DTSTART: это важно для переносов строк и экранирования iCalendar.

Шаг 6. Найдите событие в массиве events

После Read ICS откройте JSON. Ниже показан фрагмент результата, не весь объект:

json
{
  "calendar": {
    "version": "2.0",
    "events": [
      {
        "uid": "ezgpt-demo-meeting-001@example.invalid",
        "summary": "Учебная встреча",
        "start": {
          "date": "2026-10-20T10:00:00.000Z",
          "type": "DATE-TIME"
        },
        "end": {
          "date": "2026-10-20T10:30:00.000Z",
          "type": "DATE-TIME"
        }
      }
    ]
  }
}

Один входной ICS здесь превращается в один item с объектом calendar. Внутри него лежит массив events. Даже одна встреча находится по пути calendar.events[0]; автоматического превращения каждой встречи в отдельный item в этой операции нет.

Название называется summary. Начало и конец — объекты start и end, содержащие date и type. В JSON даты показаны ISO-строками UTC. Не ищите поля start_utc или title прямо в исходном результате: такие удобные имена мы зададим в проверяющем Code.

В полном объекте также будут описание, место, статус и stamp. stamp — отметка времени календарного компонента, а не начало встречи. Она может отличаться между версиями файла и не должна подменять start.

Шаг 7. Сверьте известное событие

В Check Event вставьте код:

javascript
Показать код (33 строк)
const items = $input.all();
if (items.length !== 1) throw new Error('one_calendar_required');
const item = items[0], calendar = item.json.calendar;
if (!Number.isInteger(item.json.source_bytes) || !item.binary?.document) throw new Error('source_missing');
if (calendar?.version !== '2.0' || !Array.isArray(calendar.events) || calendar.events.length !== 1) {
  throw new Error('one_event_required');
}
const e = calendar.events[0];
const keys = 'description|end|location|stamp|start|status|summary|uid';
if (Object.keys(e).sort().join('|') !== keys) throw new Error('sample_event_fields_mismatch');
const expected = {
  uid: 'ezgpt-demo-meeting-001@example.invalid', summary: 'Учебная встреча',
  description: 'Вымышленная встреча для проверки n8n.', location: 'Учебный кабинет', status: 'CONFIRMED'
};
for (const [key, value] of Object.entries(expected)) {
  if (e[key] !== value) throw new Error('sample_value_mismatch: ' + key);
}
const iso = value => {
  if (!value || value.type !== 'DATE-TIME') throw new Error('date_time_required');
  const date = new Date(value.date);
  if (!Number.isFinite(date.getTime())) throw new Error('date_invalid');
  return date.toISOString();
};
const start = iso(e.start), end = iso(e.end);
iso(e.stamp);
if (start !== '2026-10-20T10:00:00.000Z' || end !== '2026-10-20T10:30:00.000Z') {
  throw new Error('sample_time_mismatch');
}
return [{ json: {
  uid: e.uid, title: e.summary, description: e.description, location: e.location,
  start_utc: start, end_utc: end, duration_minutes: (Date.parse(end) - Date.parse(start)) / 60000,
  source_bytes: item.json.source_bytes, verified: true, action_performed: false
}, binary: item.binary }];

Сначала проверяется, что events содержит ровно один элемент, а не пустой календарь или выгрузку из нескольких встреч. Затем код сверяет UID, название, описание, место, статус и UTC-время учебного образца. Длительность считается по началу и концу.

Список допустимых полей намеренно узкий. Если появляется правило повторов, участники или другой дополнительный элемент, схема не пытается обработать его молча. Она останавливается с ошибкой проверки образца. Это не ограничение самого формата ICS и не обещание универсальной поддержки календарей.

verified: true означает совпадение с заданным учебным событием. Значение CONFIRMED прочитано из файла: оно не доказывает, что человек принял приглашение или что встреча появилась в чьём-либо календаре.

Шаг 8. Запустите всю цепочку

Нажмите Execute workflow от Manual Trigger. Все пять узлов должны завершиться успешно. В JSON Check Event ожидается:

json
{
  "uid": "ezgpt-demo-meeting-001@example.invalid",
  "title": "Учебная встреча",
  "description": "Вымышленная встреча для проверки n8n.",
  "location": "Учебный кабинет",
  "start_utc": "2026-10-20T10:00:00.000Z",
  "end_utc": "2026-10-20T10:30:00.000Z",
  "duration_minutes": 30,
  "source_bytes": 450,
  "verified": true,
  "action_performed": false
}

Сравните UID, название, время и duration_minutes: 30 с исходным файлом. source_bytes: 450 относится к нашему образцу; при других переносах строк размер может отличаться, хотя событие останется тем же. В Binary последнего узла должен сохраниться document.

Открыть проверенный JSON-результат

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

Шаг 9. Проверьте ошибку настройки

В Read ICS временно замените Destination Output Field с calendar на wrong и выполните весь workflow заново. Check Event должен завершиться с one_event_required: ожидаемого календаря в нужном поле нет. Верните calendar и повторите запуск.

Похожая ошибка возникает при выборе Extract From Text File: вместо объекта придёт строка. Не скрывайте это через Continue On Fail, Always Output Data или ручной verified: true. Сначала верните правильную операцию и повторите всю цепочку.

Отдельно проверьте время: 10:00 UTC — тот же момент, что 13:00 при UTC+3 или 15:00 при UTC+5. Нельзя просто убрать Z и считать получившееся время местным. В этой инструкции даты сохраняются в UTC, отображение для пользователя — отдельная задача.

Шаг 10. Подготовьте работу со своим ICS

Для другого разрешённого файла сначала замените URL загрузки и посмотрите JSON именно в Read ICS. Сверьте количество events, UID, summary, типы дат и наличие повторов или событий на весь день. Не подключайте чужую выгрузку к последнему Code и не ждите совпадения с нашей «Учебной встречей».

Если нужен такой же контроль известного файла, замените ожидаемые значения и согласуйте допустимые поля. Если нужны несколько встреч, сначала определите правила обработки массива. Для событий на весь день важен тип DATE, а для повторов — отдельная логика расписания; простого выбора первого элемента недостаточно.

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

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

Симптом Причина Что сделать
Нет binary.document Ответ прочитан как текст или выбран другой ключ Вернуть File и document
calendar_wrapper_required Вместо ICS пришёл другой текст Проверить ссылку и доступ
one_event_required Нет calendar или число встреч не равно одному Проверить Destination и events
source_missing Потерян JSON или исходный binary Выбрать Keep Source: Both
sample_time_mismatch Время не совпало с учебным событием Сверить DTSTART, DTEND и UTC

Границы этого примера

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

Как скачать файл через HTTP Request в n8n

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

18 октября 2026 года точный публичный workflow проверен на n8n 2.42.4 в отдельном Docker-экземпляре с binary на диске. Все 34 сценария прошли: HTTPS-образец ezgpt.ru и локальная копия, LF вместо CRLF, перенос строки iCalendar в названии, UTF-8 BOM, MIME text/calendar и application/octet-stream, другая отметка DTSTAMP; HTML и HTML под видом ICS, пустой и слишком большой файл, неверный UTF-8, NUL, отсутствие границ календаря, ноль и два события, отсутствие UID, другое название и время, повтор, участник и событие на весь день; HTTP 404 и 503, редирект, задержка, чтение ответа как JSON, неверные binary-поля и Destination, чтение как текст, потеря JSON или binary, UTF-16 вместо UTF-8. Все семь успешных вариантов дали одно проверенное событие с правильными UTC-датами и длительностью. Штатный Extract from File использовал нативный ts-ics, без ручного разбора ICS. Образец дополнительно разобран независимым icalendar 7.3.0: UID, название, описание, место и даты совпали с результатом n8n. Исходник занимает 450 байт, исходный MIME на сайте — application/octet-stream. Контейнер остановлен, существующие workflows не менялись. Клики редактора, календарный импорт, реальные выгрузки, раскрытие повторов, Cloud и запись в API не тестировались. Обложка — AI-иллюстрация.

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

Какой узел читает ICS в n8n?

Extract from File с операцией Extract From ICS. В примере он читает binary.document и записывает объект в JSON-поле calendar.

Почему после чтения один item, а встреча внутри events?

Узел вернул объект календаря. События лежат в массиве calendar.events. Эта операция не выдаёт автоматически отдельный item на каждую встречу.

Где взять название и время встречи?

У события название — summary, время — start.date и end.date. Последний Code переименовывает их в title, start_utc и end_utc.

Статус CONFIRMED подтверждает участие человека?

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

Подойдёт схема для повторяющихся встреч?

Не в текущем виде. Учебная проверка отклоняет дополнительные поля повторов. Чтение правила и построение всех экземпляров события — разные задачи.

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

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