Skip to content

Compatibilitat S3

Utilitza l'AWS SDK per pujar, descarregar i gestionar fitxers a IPFS Ninja amb el mateix codi que fas servir per a Amazon S3.

Endpoint

https://s3.ipfs.ninja

Credencials

L'API S3 utilitza la teva clau API d'IPFS Ninja per a l'autenticació. La teva clau API serveix tant com a access key com a secret key.

Com obtenir les teves credencials

  1. Ves a Dashboard > API Keys
  2. Fes clic a Create API key i dona-li un nom (p. ex. "S3 access")
  3. Copia la clau completa immediatament — només es mostra un cop i no es pot recuperar més tard

La teva clau té aquest aspecte:

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

Correspondència amb credencials AWS

Paràmetre AWSValorExemple
accessKeyIdEls primers 12 caràcters de la teva clau APIbws_628bba35
secretAccessKeyLa clau API completa (els 36 caràcters)bws_628bba35e9e0079d9ff9c392b1b55a7b
regionSempre us-east-1us-east-1

WARNING

La clau API completa només es mostra un cop quan la crees. Si la perds, elimina la clau i crea'n una de nova des de la pàgina d'API Keys.

Inici ràpid

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: QmXnnyufdzAWL5CqZ2RnSNgPbvCc1ALT73s6epPrRnZ1Xy

Buckets = Carpetes

Els buckets S3 es corresponen amb les teves carpetes d'IPFS Ninja. Quan puges un fitxer a un bucket, s'emmagatzema a la carpeta corresponent. Quan llistes objectes d'un bucket, veus els fitxers d'aquella carpeta.

Operació S3Equivalent a IPFS Ninja
CreateBucketCrear una carpeta nova
ListBucketsLlistar les teves carpetes
DeleteBucketEliminar una carpeta i tots els seus fitxers
PutObject a un bucketPujar un fitxer a la carpeta
ListObjectsV2 d'un bucketLlistar els fitxers de la carpeta
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

Les carpetes creades mitjançant l'API S3 són les mateixes carpetes visibles al teu Dashboard. Pots organitzar fitxers des de l'API S3, l'API REST o la interfície web — tots comparteixen el mateix sistema de carpetes.

INFO

A diferència d'Amazon S3, les carpetes d'IPFS Ninja són planes per defecte. Per crear estructures imbricades, utilitza els endpoints de carpetes de l'API REST amb parentFolderId. Des de l'API S3, utilitza prefixos de clau (p. ex. images/photo.png) per organitzar dins d'una carpeta.

Operacions suportades

PutObject

Puja un fitxer a IPFS. El fitxer es fixa (pin), s'analitza per seguretat i el CID es retorna a les capçaleres ETag i x-amz-meta-cid.

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

Descarrega un fitxer per la seva clau (nom de fitxer) o 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

Obté les metadades d'un fitxer sense descarregar el contingut.

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

Desfixa (unpin) un fitxer d'IPFS i elimina'l del teu compte.

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

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

ListObjectsV2

Llista els fitxers d'un bucket amb filtratge opcional per prefix i paginació.

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

Puja fitxers grans (fins a 5 GB) mitjançant multipart upload. L'AWS SDK ho gestiona automàticament:

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

O controla les parts manualment:

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

Exemple amb 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())

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

Diferències respecte a Amazon S3

FuncionalitatAmazon S3IPFS Ninja S3
Model d'emmagatzematgeObjectes mutablesAdreçament per contingut (CID immutables)
Comportament en sobreescriureSubstitueix l'objecte al llocCrea un nou CID, l'antic CID continua accessible
VersionatSuportatNo suportat (utilitza CID per al versionat)
Xifratge al servidorSuportatNo suportat (el contingut és a IPFS)
Polítiques de cicle de vidaSuportadesNo suportades
Polítiques de bucket / ACLSuportadesUtilitza els modes d'accés del gateway
URL prefirmadesSuportadesUtilitza tokens de pujada signats
Mida màxima d'objecte5 TB5 GB (multipart), 100 MB (PUT únic)
RegionsMulti-regióNomés us-east-1
Valor d'ETagHash MD5IPFS CID
Capçaleres addicionalsS3 estàndardx-amz-meta-cid (IPFS CID)

Migració des d'Amazon S3

Substitueix la configuració del teu client 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
 });

Les teves crides existents a PutObject, GetObject, ListObjectsV2 i DeleteObject funcionen sense canvis.

Migració des de Filebase

Substitueix l'URL de l'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
 });