Skip to content

Папки

Папки организуют ваши загруженные файлы в панели управления. По умолчанию они хранят только метаданные — файлы сохраняют собственные CID и не перемещаются в IPFS — но вы также можете сделать снимок папки (snapshot), чтобы материализовать её как настоящую директорию UnixFS и получить один CID для всего содержимого.

Когда стоит делать снимок папки

Снимок папки — это единый CID директории IPFS, содержащий все файлы папки, адресуемые по имени. С его помощью вы можете:

  • Поделиться всей папкой по одной ссылке: https://ipfs.ninja/ipfs/{dirCid}/
  • Разрешать https://ipfs.ninja/ipfs/{dirCid}/photo.jpg (или через любой другой шлюз) напрямую
  • Поместить CID в contenthash ENS, чтобы разместить статический сайт
  • Использовать его как базовый CID коллекции NFT, чтобы каждый токен ссылался на ipfs://{dirCid}/<id>.json
  • Закрепить директорию где угодно ещё — любой шлюз IPFS в мире умеет разрешать CID директории UnixFS

Снимки адресуются по содержимому: одинаковое содержимое папки всегда даёт одинаковый CID. Повторный снимок неизменённой папки возвращает тот же CID, что и раньше. Добавление/удаление/переименование файла даёт новый CID; предыдущий CID остаётся закреплённым и разрешимым, пока вы не удалите его файлы.

Создать папку

POST /folders

ПараметрТипОбязательныйОписание
namestringДаОтображаемое имя.
parentFolderIdstring | nullНетID родительской папки для вложенных папок. Опустите для папки корневого уровня.

Пример

bash
curl -X POST https://api.ipfs.ninja/folders \
  -H "X-Api-Key: bws_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "My NFT collection" }'

Возвращает:

json
{
  "folderId": "1f8e2c3a-…",
  "name": "My NFT collection",
  "parentFolderId": null,
  "createdAt": 1746360000000
}

У новосозданных папок нет снимка. Поле latestSnapshot появляется у папки после вызова POST /folders/{id}/snapshot (см. ниже) и в последующих ответах GET /folders.

Список папок

GET /folders

Возвращает все папки в вашем аккаунте, как корневого уровня, так и вложенные, вместе с CID последнего снимка для каждой (если он есть).

json
[
  {
    "folderId": "1f8e2c3a-…",
    "name": "My NFT collection",
    "parentFolderId": null,
    "createdAt": 1746360000000,
    "fileCount": 42,
    "latestSnapshot": {
      "cid": "QmRZx5…",
      "takenAt": 1746421000000,
      "fileCount": 42
    }
  }
]

fileCount отражает текущее содержимое папки; latestSnapshot.fileCount отражает содержимое на момент последнего снимка. Если они отличаются, CID снимка всё ещё разрешим, но устарел — сделайте новый снимок, чтобы обновить его.

Переместить файл в папку

PUT /files/{cid}/move

ПараметрТипОбязательныйОписание
folderIdstring | nullДаID целевой папки, либо null, чтобы переместить файл в корень.
bash
curl -X PUT https://api.ipfs.ninja/files/Qm.../move \
  -H "X-Api-Key: bws_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "folderId": "1f8e2c3a-…" }'

Сделать снимок папки (получить CID директории UnixFS)

POST /folders/{folderId}/snapshot

Материализует папку как настоящую директорию UnixFS в кластере IPFS и закрепляет результат. Возвращает один CID для всей папки. Имена дочерних элементов берутся из поля fileName каждого файла; дубликаты автоматически разрешаются без конфликтов.

Тело запроса не требуется; папка определяется параметром пути.

Пример

bash
curl -X POST https://api.ipfs.ninja/folders/1f8e2c3a-.../snapshot \
  -H "X-Api-Key: bws_your_api_key_here"

Возвращает:

json
{
  "ok": true,
  "folderId": "1f8e2c3a-…",
  "cid": "QmRZx5VgFHDsG7ECvaKkZBS4ydmkdAkDyaKyF71RYvh8",
  "fileCount": 42,
  "sizeBytes": 8421376,
  "takenAt": 1746421000000,
  "ipfsUrl": "https://ipfs.ninja/ipfs/QmRZx5.../"
}

CID также сохраняется в записи папки, поэтому последующие вызовы GET /folders возвращают его как latestSnapshot.cid без необходимости повторного снимка.

Разрешение снимка

Как только снимок закреплён, CID директории разрешается через любой шлюз IPFS. Простейший шаблон URL:

https://ipfs.ninja/ipfs/{dirCid}/         → directory listing
https://ipfs.ninja/ipfs/{dirCid}/photo.jpg → that one file

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

Повторные снимки

Повторный снимок неизменённой папки возвращает тот же CID — CID директорий адресуются по содержимому, поэтому одинаковое содержимое всегда даёт одинаковый хеш, а вызов закрепления в кластере распознаёт дубликат и не выполняет никаких действий на своей стороне.

Обратите внимание: сам процесс снимка не бесплатен, даже если результат — тот же CID. Каждый вызов заново считывает байты каждого файла из IPFS и повторно загружает их как multipart на endpoint /add кластера — именно там происходит обёртывание в директорию. Для типичных папок (≤100 небольших файлов) это всё ещё занимает несколько секунд; для очень больших папок предпочтительно вызывать снимок только тогда, когда содержимое действительно изменилось.

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

Ограничения

  • Папка должна содержать хотя бы один файл. Пустые папки возвращают 400 — folder is empty.
  • Символы имён файлов кодируются URL-кодированием в multipart-загрузке, принимаемой Kubo; URL шлюза могут потребовать процентного кодирования для пробелов или не-ASCII символов в именах файлов.
  • Снимки учитываются в общем лимите закреплений вашего плана ровно один раз для каждого уникального CID — блоки файлов дедуплицируются, поэтому снимок в основном добавляет лишь небольшой узел директории поверх файлов, которые вы уже закрепили.

Обновить папку

PUT /folders/{folderId}

ПараметрТипОбязательныйОписание
namestringНетНовое отображаемое имя.
parentFolderIdstring | nullНетПереместить папку к новому родителю. null перемещает её в корень.

Удалить папку

DELETE /folders/{folderId}

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

json
{
  "deleted": true,
  "filesDeleted": 42,
  "foldersDeleted": 3
}

Настройка S3 CORS для папки / bucket-а

Папки, доступные через S3-совместимый API, выступают в роли bucket-ов. Если вы работаете с этим API из браузерного JavaScript, вам нужны правила CORS на bucket-е, чтобы preflight-запросы браузера проходили успешно. Есть два эквивалентных интерфейса, сохраняющих данные в одно и то же хранилище:

  • PUT /folders/{folderId}/cors — этот REST endpoint, аутентификация через JWT (используется панелью управления)
  • S3-субресурс PUT /{bucket}?cors — аутентификация через SigV4 (используется AWS SDK, см. s3-compatibility.md)

PUT на этот endpoint также закрепляет имя папки как глобально уникальный bucket, если оно ещё не занято.

PUT /folders/{folderId}/cors

Устанавливает правила CORS для S3-bucket-а папки. До 5 правил на bucket, 64 KB суммарно.

ПараметрТипОбязательныйОписание
rulesCorsRule[]ДаМассив правил CORS в формате AWS (см. ниже). Не должен быть пустым.
bucketNamestringНетЯвное имя S3-bucket-а. По умолчанию используется отображаемое имя папки. Если желаемое имя уже занято глобально, укажите здесь альтернативу.

Каждое CorsRule:

ПолеТипОбязательныйОписание
AllowedOriginsstring[]ДаИсточники, которым разрешено отправлять запросы. Поддерживает подстановочные знаки (https://*.myapp.com). Используйте * для любого источника.
AllowedMethodsstring[]ДаОдин или несколько методов из GET, HEAD, PUT, POST, DELETE.
AllowedHeadersstring[]НетЗаголовки, которые браузеры могут включать в запросы. По умолчанию: нет. Используйте ["*"], чтобы разрешить все (рекомендуется для AWS SDK v3, который отправляет Authorization, x-amz-* и т.д.).
ExposeHeadersstring[]НетЗаголовки ответа, доступные для чтения браузерным JavaScript. Включите ETag и x-amz-meta-cid, если вашему приложению нужен возвращаемый CID.
MaxAgeSecondsnumberНетКак долго браузеры кэшируют preflight-ответ. 0-86400. По умолчанию 3600.
IDstringНетПроизвольная текстовая метка для правила.

Пример запроса

bash
curl -X PUT https://api.ipfs.ninja/folders/17f6dfd8-519c-4d0e-8f3a-5988a1d34ef2/cors \
  -H "Authorization: Bearer $COGNITO_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [{
      "AllowedOrigins": ["https://myapp.com", "http://localhost:3000"],
      "AllowedMethods": ["GET", "HEAD", "PUT", "POST", "DELETE"],
      "AllowedHeaders": ["*"],
      "ExposeHeaders": ["ETag", "x-amz-meta-cid", "x-amz-request-id"],
      "MaxAgeSeconds": 3600
    }]
  }'

Ответ 200 OK

json
{ "success": true, "rules": [ { "AllowedOrigins": ["https://myapp.com", "http://localhost:3000"], "AllowedMethods": ["GET", "HEAD", "PUT", "POST", "DELETE"], "AllowedHeaders": ["*"], "ExposeHeaders": ["ETag", "x-amz-meta-cid", "x-amz-request-id"], "MaxAgeSeconds": 3600 } ] }

GET /folders/{folderId}/cors

Возвращает текущие правила CORS и имя bucket-а (если оно занято).

json
{
  "rules": [  ],
  "bucketName": "my-project"
}

DELETE /folders/{folderId}/cors

Удаляет все правила CORS. Preflight-запросы браузера к bucket-у будут отклоняться, пока не будут заданы новые правила.

Альтернатива через панель управления

На странице «Файлы» в меню действий каждой папки есть пункт S3 CORS, открывающий редактор в виде формы. Использует то же самое хранилище, что и этот REST endpoint, и что PutBucketCors через API S3.