Skip to content

S3 kompatibilnost

Koristite AWS SDK za prijenos, preuzimanje i upravljanje datotekama na IPFS Ninja s istim kodom koji koristite za Amazon S3.

Endpoint

https://s3.ipfs.ninja

Vjerodajnice

S3 API koristi vaš IPFS Ninja API ključ za autentifikaciju. Vaš API ključ služi i kao pristupni ključ (access key) i kao tajni ključ (secret key).

Kako dobiti vjerodajnice

  1. Idite na Nadzorna ploča > API ključevi
  2. Kliknite Create API key i dajte mu naziv (npr. "S3 pristup")
  3. Odmah kopirajte cijeli ključ — prikazuje se samo jednom i ne može se naknadno dohvatiti

Vaš ključ izgleda ovako:

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

Mapiranje na AWS vjerodajnice

AWS parametarVrijednostPrimjer
accessKeyIdPrvih 12 znakova vašeg API ključabws_628bba35
secretAccessKeyCijeli API ključ (svih 36 znakova)bws_628bba35e9e0079d9ff9c392b1b55a7b
regionUvijek us-east-1us-east-1

WARNING

Cijeli API ključ prikazuje se samo jednom kada ga stvorite. Ako ga izgubite, obrišite ključ i stvorite novi na stranici API ključeva.

Brzi početak

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

S3 buckets mapiraju se na vaše IPFS Ninja mape. Kada prenesete datoteku u bucket, ona se sprema u odgovarajuću mapu. Kada listate objekte u bucketu, vidite datoteke u toj mapi.

S3 operacijaIPFS Ninja ekvivalent
CreateBucketStvori novu mapu
ListBucketsListaj svoje mape
DeleteBucketObriši mapu i sve datoteke u njoj
PutObject u bucketPrenesi datoteku u mapu
ListObjectsV2 na bucketuListaj datoteke u mapi
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

Mape stvorene putem S3 API-ja iste su mape vidljive na vašoj Nadzornoj ploči. Možete organizirati datoteke putem S3 API-ja, REST API-ja ili web sučelja — svi dijele isti sustav mapa.

INFO

Za razliku od Amazon S3, IPFS Ninja mape su prema zadanom ravne. Za stvaranje ugniježđenih struktura koristite REST API endpointe za mape s parentFolderId. Iz S3 API-ja koristite prefikse ključeva (npr. images/photo.png) za organizaciju unutar mape.

Nazivi bucketa jedinstveni su globalno

Nazivi bucketa žive u globalnom imenskom prostoru kod svih korisnika, u skladu sa semantikom AWS S3. To znači:

  • Prvi korisnik koji stvori bucket s određenim nazivom preuzima taj naziv globalno.
  • Kasniji pozivi CreateBucket s istim nazivom, s bilo kojeg računa, vraćaju BucketAlreadyExists (409).
  • Ako pokušate ponovno stvoriti vlastiti bucket, dobit ćete BucketAlreadyOwnedByYou (409).
  • Naziv vaše mape u nadzornoj ploči vezan je uz račun i i dalje može biti bilo što — samo naziv bucketa vidljiv u S3-u prolazi kroz globalni imenski prostor.

Ako je naziv koji želite već zauzet, odaberite drukčije definiran naziv (myapp-photos-2026, acme-nft-metadata) — ista konvencija koju biste koristili na Amazon S3.

Podržane operacije

PutObject

Prenesite datoteku na IPFS. Datoteka se prikvačuje, sigurnosno skenira, a CID se vraća u ETag i x-amz-meta-cid zaglavljima.

Za uvoz CAR datoteke umjesto obične datoteke, dodajte metapodatkovno zaglavlje x-amz-meta-import: car. Pogledajte Uvoz CAR datoteka za detalje.

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

Preuzmite datoteku prema njezinom ključu (nazivu datoteke) ili CID-u.

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

Dohvatite metapodatke datoteke bez preuzimanja sadržaja.

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

Otkvačite datoteku s IPFS-a i obrišite je sa svog računa.

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

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

ListObjectsV2

Listajte datoteke u bucketu s opcionalnim filtriranjem prefiksom i paginacijom.

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

Prenesite velike datoteke (do 5 GB) koristeći multipart upload. AWS SDK to obrađuje automatski:

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

Ili ručno kontrolirajte dijelove:

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 primjer

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 primjer

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

Konfiguracija CORS-a (pristup putem SDK-a iz preglednika)

Ako pozivate S3 API izravno iz JavaScripta u pregledniku (SPA, wallet aplikacija, alat za nadzornu ploču), prvo morate konfigurirati CORS na bucketu. U suprotnom preglednici blokiraju preflight zahtjev i vaši prijenosi neće uspjeti uz grešku No 'Access-Control-Allow-Origin' header is present.

Ista struktura kao kod AWS S3 — poduresursi 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" }));

Ograničenje i zadane vrijednosti

  • Do 5 pravila po bucketu (specifikacija dopušta 100; mi ograničavamo na 5 kako bismo preflight odgovor za preglednik održali kompaktnim).
  • Ukupna konfiguracija ograničena je na 64 KB serijaliziranih podataka.
  • Ako CORS konfiguracija nije postavljena, preflight zahtjevi iz preglednika se odbijaju — u skladu sa zadanim ponašanjem Amazon S3. Konfigurirajte eksplicitna pravila za izvore (origins) s kojih zaista poslužujete sadržaj.

Napomena o sigurnosti u praksi

CORS je pogodnost na strani preglednika, ne sigurnosna granica. Svaki S3 API poziv i dalje zahtijeva valjan SigV4 potpis izračunat iz vašeg API ključa — permisivna CORS konfiguracija ne dopušta nikome korištenje vašeg bucketa bez te vjerodajnice. Ono što CORS sprječava jest da neplanirani izvor (npr. zastarjela kopija vaše aplikacije na dev.myapp.com) šalje potpisane zahtjeve iz konteksta preglednika.

Alternativa putem nadzorne ploče

Stranica Datoteke ima stavku S3 CORS u izborniku radnji svake mape. Riječ je o istoj pohrani u pozadini; ako ne želite pisati kod za PutBucketCors, konfigurirajte ga ondje.

Razlike u odnosu na Amazon S3

ZnačajkaAmazon S3IPFS Ninja S3
Model pohranePromjenjivi objektiAdresiranje sadržajem (nepromjenjivi CID-ovi)
Ponašanje pri prepisivanjuZamjenjuje objekt na mjestuStvara novi CID, stari CID i dalje dostupan
VerzioniranjePodržanoNije podržano (koristite CID-ove za verzioniranje)
Enkripcija na strani poslužiteljaPodržanaNije podržana (sadržaj je na IPFS-u)
Politike životnog ciklusaPodržaneNisu podržane
Politike bucketa / ACL-oviPodržaniKoristite načine pristupa gatewayu
Prethodno potpisani URL-oviPodržaniKoristite potpisane tokene za prijenos
Maksimalna veličina objekta5 TB5 GB (multipart), 100 MB (pojedinačni PUT)
RegijeViše regijaSamo us-east-1
Vrijednost ETagMD5 hashIPFS CID
Dodatna zaglavljaStandardni S3x-amz-meta-cid (IPFS CID)
Format CID-aN/AModerni CIDv1 (bafy…) za nove prijenose; stariji Qm… i dalje je valjan kao ulaz
Imenski prostor bucketaGlobalan (na razini cijelog AWS-a)Globalan (kod svih IPFS Ninja korisnika) — ista semantika
CORSPodržan PutBucketCorsPodržan PutBucketCors (ograničenje od 5 pravila)

Migracija s Amazon S3

Zamijenite konfiguraciju svog S3 klijenta:

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

Vaši postojeći pozivi PutObject, GetObject, ListObjectsV2 i DeleteObject rade bez promjena.

Migracija s Filebase

Zamijenite URL endpointa:

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