Skip to content

Compatibilitate S3

Folosiți SDK-ul AWS pentru a încărca, descărca și gestiona fișiere pe IPFS Ninja cu același cod pe care îl folosiți pentru Amazon S3.

Endpoint

https://s3.ipfs.ninja

Credențiale

API-ul S3 folosește cheia dvs. de API IPFS Ninja pentru autentificare. Cheia dvs. de API servește atât drept access key, cât și drept secret key.

Cum să obțineți credențialele

  1. Accesați Dashboard > API Keys
  2. Apăsați Create API key și dați-i un nume (ex: „S3 access")
  3. Copiați cheia completă imediat — este afișată o singură dată și nu poate fi recuperată ulterior

Cheia dvs. arată astfel:

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

Maparea la credențiale AWS

Parametru AWSValoareExemplu
accessKeyIdPrimele 12 caractere ale cheii dvs. de APIbws_628bba35
secretAccessKeyCheia de API completă (toate cele 36 de caractere)bws_628bba35e9e0079d9ff9c392b1b55a7b
regionÎntotdeauna us-east-1us-east-1

WARNING

Cheia de API completă este afișată o singură dată când o creați. Dacă o pierdeți, ștergeți cheia și creați una nouă din pagina API Keys.

Start rapid

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 = Foldere

Bucket-urile S3 corespund folderelor dvs. din IPFS Ninja. Când încărcați un fișier într-un bucket, acesta este stocat în folderul corespunzător. Când listați obiectele dintr-un bucket, vedeți fișierele din acel folder.

Operație S3Echivalent IPFS Ninja
CreateBucketCreează un folder nou
ListBucketsListează folderele dvs.
DeleteBucketȘterge un folder și toate fișierele din el
PutObject în bucketÎncarcă fișier în folder
ListObjectsV2 pe bucketListează fișierele din folder
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

Folderele create prin API-ul S3 sunt aceleași foldere vizibile în Dashboard-ul dvs. Puteți organiza fișiere atât din API-ul S3, cât și din API-ul REST, sau din interfața web — toate împart același sistem de foldere.

INFO

Spre deosebire de Amazon S3, folderele IPFS Ninja sunt plate în mod implicit. Pentru a crea structuri ierarhice, folosiți endpoint-urile de foldere din API-ul REST cu parentFolderId. Din API-ul S3, folosiți prefixe în chei (ex: images/photo.png) pentru a organiza în cadrul unui folder.

Numele bucket-urilor sunt unice global

Numele bucket-urilor există într-un spațiu de nume global pentru toți clienții, la fel ca semantica AWS S3. Aceasta înseamnă:

  • Primul utilizator care creează un bucket cu un anumit nume revendică acel nume la nivel global.
  • Apelurile CreateBucket ulterioare cu același nume din orice cont returnează BucketAlreadyExists (409).
  • Dacă încercați să recreați propriul bucket, primiți BucketAlreadyOwnedByYou (409).
  • Numele folderului dvs. din dashboard este per cont și poate fi oricare — doar numele de bucket vizibil prin S3 trece prin spațiul de nume global.

Dacă un nume dorit este deja luat, alegeți unul cu un domeniu de aplicare diferit (myapp-photos-2026, acme-nft-metadata) — aceeași convenție pe care ați folosi-o pe Amazon S3.

Operații acceptate

PutObject

Încărcați un fișier pe IPFS. Fișierul este fixat, scanat pentru securitate, iar CID-ul este returnat în anteturile ETag și x-amz-meta-cid.

Pentru a importa un fișier CAR în loc de un fișier obișnuit, adăugați antetul de metadate x-amz-meta-import: car. Consultați Import CAR pentru detalii.

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

Descărcați un fișier după cheia sa (numele fișierului) sau 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

Obțineți metadatele fișierului fără a descărca conținutul.

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

Anulați fixarea unui fișier de pe IPFS și ștergeți-l din contul dvs.

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

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

ListObjectsV2

Listați fișierele dintr-un bucket cu filtrare opțională după prefix și paginare.

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

Încărcați fișiere mari (până la 5 GB) folosind încărcarea multipart. SDK-ul AWS gestionează asta automat:

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);

Sau controlați părțile manual:

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 }]
  }
}));

Exemplu 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())

Exemplu 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!")
}

Configurarea CORS (acces din SDK-ul de browser)

Dacă apelați API-ul S3 direct din JavaScript de browser (SPA, aplicație wallet, unealtă de dashboard), trebuie să configurați mai întâi CORS pe bucket. În caz contrar, browserele blochează preflight-ul și încărcările dvs. eșuează cu No 'Access-Control-Allow-Origin' header is present.

Aceeași formă ca AWS S3 — subresursele 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" }));

Limită și valori implicite

  • Până la 5 reguli per bucket (specificația permite 100; noi limităm la 5 pentru a păstra răspunsul de preflight al browserului compact).
  • Configurația totală este limitată la 64 KB serializați.
  • Dacă nu este setată nicio configurație CORS, preflight-urile browserului sunt respinse — la fel ca postura implicită a AWS S3. Configurați reguli explicite pentru originile de pe care serviți efectiv.

Notă reală de securitate

CORS este un strat de conveniență pe partea de browser, nu o graniță de securitate. Fiecare apel al API-ului S3 necesită în continuare o semnătură SigV4 validă calculată din cheia dvs. de API — o configurație CORS permisivă nu permite nimănui să folosească bucket-ul dvs. fără acea credențială. Ce previne totuși CORS: o origine neintenționată (de ex. o copie învechită a aplicației dvs. pe dev.myapp.com) care trimite cereri semnate dintr-un context de browser.

Alternativă din dashboard

Pagina Fișiere are o intrare S3 CORS în meniul de acțiuni al fiecărui folder. Aceeași stocare de bază; dacă nu doriți să scrieți cod PutBucketCors, configurați-l acolo.

Diferențe față de Amazon S3

FuncționalitateAmazon S3IPFS Ninja S3
Model de stocareObiecte mutabileAdresare după conținut (CID-uri imutabile)
Comportament la suprascriereÎnlocuiește obiectul pe locCreează CID nou, CID-ul vechi rămâne accesibil
VersionareSuportatăNesuportată (folosiți CID-uri pentru versionare)
Criptare pe serverSuportatăNesuportată (conținutul este pe IPFS)
Politici de ciclu de viațăSuportateNesuportate
Politici de bucket / ACL-uriSuportateFolosiți modurile de acces gateway
URL-uri pre-semnateSuportateFolosiți tokenuri de încărcare semnate
Dimensiune maximă obiect5 TB5 GB (multipart), 100 MB (PUT singular)
RegiuniMulti-regiuneDoar us-east-1
Valoare ETagHash MD5IPFS CID
Antete suplimentareS3 standardx-amz-meta-cid (IPFS CID)
Format CIDN/ACIDv1 modern (bafy…) pentru încărcările noi; Qm… vechi rămâne valid ca intrare
Spațiu de nume bucketGlobal (la nivel AWS)Global (pentru toate conturile IPFS Ninja) — aceeași semantică
CORSPutBucketCors suportatPutBucketCors suportat (limită de 5 reguli)

Migrare de la Amazon S3

Înlocuiți configurația clientului 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
 });

Apelurile dvs. existente PutObject, GetObject, ListObjectsV2 și DeleteObject funcționează fără modificări.

Migrare de la Filebase

Înlocuiți URL-ul endpoint-ului:

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
 });