Skip to content

Совместимость с S3

Используйте AWS SDK для загрузки, скачивания и управления файлами на IPFS Ninja с тем же кодом, который вы используете для Amazon S3.

Endpoint

https://s3.ipfs.ninja

Учётные данные

API S3 использует ваш API-ключ IPFS Ninja для аутентификации. Ваш API-ключ служит одновременно как access key и secret key.

Как получить учётные данные

  1. Перейдите в Dashboard > API Keys
  2. Нажмите Create API key и задайте имя (например, "S3 access")
  3. Скопируйте полный ключ сразу — он показывается только один раз и не может быть восстановлен позже

Ваш ключ выглядит так:

bws_628bba35e9e0079d9ff9c392b1b55a7b
├──────────┘└──────────────────────────┘
 prefix (12 chars)    rest of key

Сопоставление с учётными данными AWS

Параметр AWSЗначениеПример
accessKeyIdПервые 12 символов вашего API-ключаbws_628bba35
secretAccessKeyПолный API-ключ (все 36 символов)bws_628bba35e9e0079d9ff9c392b1b55a7b
regionВсегда us-east-1us-east-1

WARNING

Полный API-ключ показывается только один раз при создании. Если вы его потеряете, удалите ключ и создайте новый на странице API Keys.

Быстрый старт

javascript
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  endpoint: "https://s3.ipfs.ninja",
  credentials: {
    accessKeyId: "bws_628bba35",
    secretAccessKey: "bws_628bba35e9e0079d9ff9c392b1b55a7b"
  },
  region: "us-east-1",
  forcePathStyle: true
});

// Upload a file
const put = await s3.send(new PutObjectCommand({
  Bucket: "my-project",
  Key: "hello.json",
  Body: JSON.stringify({ hello: "IPFS" }),
  ContentType: "application/json"
}));

console.log("CID:", put.Metadata?.cid);
// CID: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

Buckets = Папки

Bucket-ы S3 соответствуют вашим папкам в IPFS Ninja. Когда вы загружаете файл в bucket, он сохраняется в соответствующей папке. Когда вы перечисляете объекты в bucket-е, вы видите файлы в этой папке.

Операция S3Эквивалент в IPFS Ninja
CreateBucketСоздать новую папку
ListBucketsПоказать ваши папки
DeleteBucketУдалить папку и все файлы в ней
PutObject в bucketЗагрузить файл в папку
ListObjectsV2 для bucketПоказать файлы в папке
javascript
import { ListBucketsCommand, CreateBucketCommand, PutObjectCommand } from "@aws-sdk/client-s3";

// Create a bucket (= create a folder)
await s3.send(new CreateBucketCommand({ Bucket: "nft-metadata" }));

// Upload a file into the folder
await s3.send(new PutObjectCommand({
  Bucket: "nft-metadata",      // ← folder name
  Key: "token-42.json",        // ← filename within the folder
  Body: JSON.stringify({ name: "My NFT #42" })
}));

// List buckets (= list your folders)
const { Buckets } = await s3.send(new ListBucketsCommand({}));
console.log(Buckets);
// [{ Name: "nft-metadata", CreationDate: "2026-04-13T..." }]

TIP

Папки, созданные через API S3, — это те же папки, которые видны в вашем Dashboard. Вы можете организовывать файлы через API S3, REST API или веб-интерфейс — все они используют одну и ту же систему папок.

INFO

В отличие от Amazon S3, папки IPFS Ninja по умолчанию плоские. Для создания вложенных структур используйте endpoint-ы папок REST API с parentFolderId. Через API S3 используйте префиксы ключей (например, images/photo.png) для организации внутри папки.

Имена bucket-ов глобально уникальны

Имена bucket-ов находятся в глобальном пространстве имён для всех клиентов, что соответствует семантике AWS S3. Это означает:

  • Первый пользователь, создавший bucket с данным именем, закрепляет это имя глобально.
  • Последующие вызовы CreateBucket с тем же именем от любого аккаунта возвращают BucketAlreadyExists (409).
  • Если вы попытаетесь повторно создать свой собственный bucket, вы получите BucketAlreadyOwnedByYou (409).
  • Имя вашей папки в панели управления привязано к аккаунту и может оставаться каким угодно — только видимое в S3 имя bucket-а проходит через глобальное пространство имён.

Если желаемое имя занято, выберите имя с иным охватом (myapp-photos-2026, acme-nft-metadata) — тот же приём, что вы использовали бы в Amazon S3.

Поддерживаемые операции

PutObject

Загружает файл в IPFS. Файл закрепляется (pin), проходит проверку безопасности, а CID возвращается в заголовках ETag и x-amz-meta-cid.

Чтобы вместо обычного файла импортировать CAR-файл, добавьте заголовок метаданных x-amz-meta-import: car. Подробности см. в Импорт CAR.

javascript
import { PutObjectCommand } from "@aws-sdk/client-s3";
import fs from "fs";

const result = await s3.send(new PutObjectCommand({
  Bucket: "my-project",
  Key: "photo.png",
  Body: fs.readFileSync("photo.png"),
  ContentType: "image/png"
}));

console.log("CID:", result.ETag);
bash
# curl equivalent
curl -X PUT "https://s3.ipfs.ninja/my-project/photo.png" \
  --data-binary @photo.png \
  -H "Content-Type: image/png" \
  --aws-sigv4 "aws:amz:us-east-1:s3" \
  --user "bws_628bba35:bws_628bba35e9e0079d9ff9c392b1b55a7b"

GetObject

Скачивает файл по его ключу (имени файла) или CID.

javascript
import { GetObjectCommand } from "@aws-sdk/client-s3";

const result = await s3.send(new GetObjectCommand({
  Bucket: "my-project",
  Key: "photo.png"
}));

const body = await result.Body.transformToByteArray();
console.log("Size:", body.length);
console.log("CID:", result.Metadata?.cid);

HeadObject

Получает метаданные файла без скачивания содержимого.

javascript
import { HeadObjectCommand } from "@aws-sdk/client-s3";

const head = await s3.send(new HeadObjectCommand({
  Bucket: "my-project",
  Key: "photo.png"
}));

console.log("Size:", head.ContentLength);
console.log("Type:", head.ContentType);
console.log("CID:", head.Metadata?.cid);

DeleteObject

Открепляет (unpin) файл от IPFS и удаляет его из вашего аккаунта.

javascript
import { DeleteObjectCommand } from "@aws-sdk/client-s3";

await s3.send(new DeleteObjectCommand({
  Bucket: "my-project",
  Key: "photo.png"
}));

ListObjectsV2

Перечисляет файлы в bucket-е с опциональной фильтрацией по префиксу и пагинацией.

javascript
import { ListObjectsV2Command } from "@aws-sdk/client-s3";

const list = await s3.send(new ListObjectsV2Command({
  Bucket: "my-project",
  Prefix: "images/",
  MaxKeys: 100
}));

for (const obj of list.Contents ?? []) {
  console.log(obj.Key, obj.Size, obj.ETag); // ETag = CID
}

Multipart Upload

Загружайте большие файлы (до 5 GB) с помощью multipart upload. AWS SDK обрабатывает это автоматически:

javascript
import { Upload } from "@aws-sdk/lib-storage";
import fs from "fs";

const upload = new Upload({
  client: s3,
  params: {
    Bucket: "my-project",
    Key: "large-dataset.tar.gz",
    Body: fs.createReadStream("large-dataset.tar.gz"),
    ContentType: "application/gzip"
  },
  partSize: 10 * 1024 * 1024, // 10 MB per part
});

upload.on("httpUploadProgress", (progress) => {
  console.log(`Uploaded ${progress.loaded} of ${progress.total} bytes`);
});

const result = await upload.done();
console.log("CID:", result.ETag);

Или управляйте частями вручную:

javascript
import {
  CreateMultipartUploadCommand,
  UploadPartCommand,
  CompleteMultipartUploadCommand
} from "@aws-sdk/client-s3";

// 1. Start
const { UploadId } = await s3.send(new CreateMultipartUploadCommand({
  Bucket: "my-project",
  Key: "big-file.bin"
}));

// 2. Upload parts
const part1 = await s3.send(new UploadPartCommand({
  Bucket: "my-project",
  Key: "big-file.bin",
  UploadId,
  PartNumber: 1,
  Body: chunk1
}));

// 3. Complete
const result = await s3.send(new CompleteMultipartUploadCommand({
  Bucket: "my-project",
  Key: "big-file.bin",
  UploadId,
  MultipartUpload: {
    Parts: [{ PartNumber: 1, ETag: part1.ETag }]
  }
}));

Пример на Python

python
import boto3

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.ipfs.ninja",
    aws_access_key_id="bws_628bba35",
    aws_secret_access_key="bws_628bba35e9e0079d9ff9c392b1b55a7b",
    region_name="us-east-1"
)

# Upload
s3.put_object(
    Bucket="my-project",
    Key="data.json",
    Body=b'{"hello": "IPFS"}',
    ContentType="application/json"
)

# List files
response = s3.list_objects_v2(Bucket="my-project")
for obj in response.get("Contents", []):
    print(obj["Key"], obj["Size"])

# Download
result = s3.get_object(Bucket="my-project", Key="data.json")
print(result["Body"].read())

Пример на Go

go
package main

import (
    "context"
    "fmt"
    "strings"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/credentials"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
    client := s3.New(s3.Options{
        BaseEndpoint: aws.String("https://s3.ipfs.ninja"),
        Region:       "us-east-1",
        Credentials:  credentials.NewStaticCredentialsProvider("bws_628bba35", "bws_628bba35e9e0...", ""),
        UsePathStyle: true,
    })

    _, err := client.PutObject(context.TODO(), &s3.PutObjectInput{
        Bucket:      aws.String("my-project"),
        Key:         aws.String("hello.txt"),
        Body:        strings.NewReader("Hello, IPFS!"),
        ContentType: aws.String("text/plain"),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("Uploaded!")
}

Настройка CORS (доступ из браузерного SDK)

Если вы вызываете API S3 напрямую из браузерного JavaScript (SPA, wallet-приложение, инструмент панели управления), сначала нужно настроить CORS на bucket-е. Иначе браузеры блокируют preflight-запрос, и ваши загрузки завершаются ошибкой No 'Access-Control-Allow-Origin' header is present.

Та же структура, что и в AWS S3 — субресурсы PutBucketCors / GetBucketCors / DeleteBucketCors:

PutBucketCors

javascript
import { S3Client, PutBucketCorsCommand } from "@aws-sdk/client-s3";

await s3.send(new PutBucketCorsCommand({
  Bucket: "my-bucket",
  CORSConfiguration: {
    CORSRules: [{
      AllowedOrigins: ["http://localhost:3000", "https://myapp.com"],
      AllowedMethods: ["GET", "HEAD", "PUT", "POST", "DELETE"],
      AllowedHeaders: ["*"],
      ExposeHeaders: ["ETag", "x-amz-meta-cid", "x-amz-request-id"],
      MaxAgeSeconds: 3600,
    }],
  },
}));

GetBucketCors

javascript
import { GetBucketCorsCommand } from "@aws-sdk/client-s3";

const { CORSRules } = await s3.send(new GetBucketCorsCommand({ Bucket: "my-bucket" }));
console.log(CORSRules);

DeleteBucketCors

javascript
import { DeleteBucketCorsCommand } from "@aws-sdk/client-s3";

await s3.send(new DeleteBucketCorsCommand({ Bucket: "my-bucket" }));

Лимиты и значения по умолчанию

  • До 5 правил на bucket (спецификация допускает 100; мы ограничиваем до 5, чтобы ответ preflight в браузере оставался компактным).
  • Общий размер конфигурации ограничен 64 KB в сериализованном виде.
  • Если конфигурация CORS не задана, preflight-запросы браузера отклоняются — как и в поведении AWS S3 по умолчанию. Настройте явные правила для источников, с которых вы реально обслуживаете запросы.

Важное замечание о безопасности

CORS — это уровень удобства на стороне браузера, а не граница безопасности. Каждый вызов API S3 всё равно требует действительной подписи SigV4, вычисленной из вашего API-ключа — разрешительная конфигурация CORS не даёт никому использовать ваш bucket без этих учётных данных. Что CORS действительно предотвращает: отправку подписанных запросов из браузерного контекста с непредусмотренного источника (например, устаревшей копии вашего приложения на dev.myapp.com).

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

На странице «Файлы» в меню действий каждой папки есть пункт S3 CORS. То же самое базовое хранилище; если вы не хотите писать код для PutBucketCors, настройте это там.

Отличия от Amazon S3

ФункцияAmazon S3IPFS Ninja S3
Модель храненияИзменяемые объектыКонтентная адресация (неизменяемые CID)
Поведение при перезаписиЗаменяет объект на местеСоздаёт новый CID, старый CID остаётся доступным
ВерсионированиеПоддерживаетсяНе поддерживается (используйте CID для версионирования)
Шифрование на сервереПоддерживаетсяНе поддерживается (контент находится в IPFS)
Политики жизненного циклаПоддерживаютсяНе поддерживаются
Политики bucket / ACLПоддерживаютсяИспользуйте режимы доступа шлюза
Предподписанные URLПоддерживаютсяИспользуйте подписанные токены загрузки
Максимальный размер объекта5 TB5 GB (multipart), 100 MB (одиночный PUT)
РегионыМультирегионТолько us-east-1
Значение ETagХеш MD5IPFS CID
Дополнительные заголовкиСтандартные S3x-amz-meta-cid (IPFS CID)
Формат CIDН/ДСовременный CIDv1 (bafy…) для новых загрузок; устаревшие Qm… остаются допустимыми на вход
Пространство имён bucket-овГлобальное (в рамках AWS)Глобальное (среди всех аккаунтов IPFS Ninja) — та же семантика
CORSПоддерживается PutBucketCorsПоддерживается PutBucketCors (лимит 5 правил)

Миграция с Amazon S3

Замените конфигурацию вашего S3-клиента:

diff
 const s3 = new S3Client({
+  endpoint: "https://s3.ipfs.ninja",
   credentials: {
-    accessKeyId: "AKIA...",
-    secretAccessKey: "wJalrX..."
+    accessKeyId: "bws_628bba35",
+    secretAccessKey: "bws_628bba35e9e0..."
   },
   region: "us-east-1",
+  forcePathStyle: true
 });

Ваши существующие вызовы PutObject, GetObject, ListObjectsV2 и DeleteObject продолжат работать без изменений.

Миграция с Filebase

Замените URL endpoint-а:

diff
 const s3 = new S3Client({
-  endpoint: "https://s3.filebase.com",
+  endpoint: "https://s3.ipfs.ninja",
   credentials: {
-    accessKeyId: "FILEBASE_KEY",
-    secretAccessKey: "FILEBASE_SECRET"
+    accessKeyId: "bws_628bba35",
+    secretAccessKey: "bws_628bba35e9e0..."
   },
   region: "us-east-1",
   forcePathStyle: true
 });