Skip to content

S3 съвместимост

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

Endpoint

https://s3.ipfs.ninja

Идентификационни данни

S3 API използва вашия IPFS Ninja API ключ за удостоверяване. Вашият 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 = Папки

S3 bucket-ите се съпоставят с вашите папки в 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

Папките, създадени чрез S3 API, са същите папки, видими в Dashboard. Можете да организирате файлове от S3 API, REST API или уеб интерфейса — всички споделят една и съща файлова система.

INFO

За разлика от Amazon S3, папките в IPFS Ninja са плоски по подразбиране. За да създадете вложени структури, използвайте endpoint-ите за папки на REST API с parentFolderId. От S3 API използвайте префикси на ключове (напр. 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. Файлът се закача, сканира за сигурност и 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

Премахване на закачането на файл от 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 в браузър)

Ако извиквате S3 API директно от 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 е удобен слой от страна на браузъра, а не граница на сигурността. Всяко извикване на S3 API все още изисква валиден SigV4 подпис, изчислен от вашия API ключ — разрешителна CORS конфигурация не позволява на никого да използва вашия bucket без този идентификационен данни. Това, което CORS предотвратява: нежелан произход (напр. остаряло копие на вашето приложение на dev.myapp.com), изпращащ подписани заявки от контекст на браузър.

Алтернатива в таблото за управление

Страницата с файлове има запис S3 CORS в менюто с действия на всяка папка. Същото основно съхранение; ако не искате да пишете код за PutBucketCors, конфигурирайте го там.

Разлики спрямо Amazon S3

ФункцияAmazon S3IPFS Ninja S3
Модел на съхранениеМутируеми обектиАдресиране по съдържание (неизменяеми CID)
Поведение при презаписванеЗаменя обекта на мястоСъздава нов CID, старият CID остава достъпен
ВерсиониранеПоддържа сеНе се поддържа (използвайте CID за версиониране)
Криптиране от страна на сървъраПоддържа сеНе се поддържа (съдържанието е в IPFS)
Политики за жизнен цикълПоддържат сеНе се поддържат
Bucket политики / ACLПоддържат сеИзползвайте режими за достъп на gateway
Предварително подписани URLПоддържат сеИзползвайте подписани токени за качване
Максимален размер на обект5 TB5 GB (multipart), 100 MB (единичен PUT)
РегиониМножество региониСамо us-east-1
Стойност на ETagMD5 хешIPFS 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
 });