Skip to content

S3-kompatibilitet

Brug AWS SDK til at uploade, downloade og administrere filer på IPFS Ninja med den samme kode, du bruger til Amazon S3.

Endpoint

https://s3.ipfs.ninja

Legitimationsoplysninger

S3 API bruger din IPFS Ninja API-nøgle til godkendelse. Din API-nøgle fungerer som både access key og secret key.

Sådan får du dine legitimationsoplysninger

  1. Gå til Dashboard > API Keys
  2. Klik på Create API key og giv den et navn (f.eks. "S3 access")
  3. Kopiér den fulde nøgle med det samme — den vises kun én gang og kan ikke hentes senere

Din nøgle ser sådan ud:

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

Mapping til AWS-legitimationsoplysninger

AWS-parameterVærdiEksempel
accessKeyIdDe første 12 tegn af din API-nøglebws_628bba35
secretAccessKeyDen fulde API-nøgle (alle 36 tegn)bws_628bba35e9e0079d9ff9c392b1b55a7b
regionAltid us-east-1us-east-1

WARNING

Den fulde API-nøgle vises kun én gang, når du opretter den. Hvis du mister den, skal du slette nøglen og oprette en ny fra API Keys-siden.

Hurtig start

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

S3-buckets svarer til dine mapper i IPFS Ninja. Når du uploader en fil til en bucket, gemmes den i den tilsvarende mappe. Når du lister objekter i en bucket, ser du filerne i den mappe.

S3-operationIPFS Ninja-ækvivalent
CreateBucketOpret en ny mappe
ListBucketsList dine mapper
DeleteBucketSlet en mappe og alle filer i den
PutObject til bucketUpload fil til mappen
ListObjectsV2 på bucketList filer i mappen
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

Mapper oprettet via S3 API er de samme mapper, der er synlige i dit Dashboard. Du kan organisere filer fra S3 API, REST API eller webgrænsefladen — de deler alle det samme mappesystem.

INFO

I modsætning til Amazon S3 er IPFS Ninja-mapper flade som standard. For at oprette indlejrede strukturer, brug REST API's mappe-endpoints med parentFolderId. Fra S3 API, brug nøglepræfikser (f.eks. images/photo.png) til at organisere inden for en mappe.

Bucket-navne er globalt unikke

Bucket-navne findes i et globalt navnerum på tværs af alle kunder, i overensstemmelse med AWS S3-semantik. Det betyder:

  • Den første bruger, der opretter en bucket med et givet navn, kræver det navn globalt.
  • Senere CreateBucket-kald med samme navn fra enhver konto returnerer BucketAlreadyExists (409).
  • Hvis du forsøger at genoprette din egen bucket, får du BucketAlreadyOwnedByYou (409).
  • Dit mappe-navn i dashboardet er per konto og kan stadig være hvad som helst — kun det S3-synlige bucket-navn går gennem det globale navnerum.

Hvis et ønsket navn er optaget, vælg et anderledes afgrænset navn (myapp-photos-2026, acme-nft-metadata) — samme konvention, som du ville bruge på Amazon S3.

Understøttede operationer

PutObject

Upload en fil til IPFS. Filen pinnes, sikkerhedsscannes, og CID returneres i ETag- og x-amz-meta-cid-headerne.

For at importere en CAR-fil i stedet for en almindelig fil, tilføj metadata-headeren x-amz-meta-import: car. Se CAR-import for detaljer.

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

Download en fil via dens nøgle (filnavn) eller 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

Hent filmetadata uden at downloade indholdet.

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

Fjern pinning af en fil fra IPFS og slet den fra din konto.

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

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

ListObjectsV2

List filer i en bucket med valgfri præfiksfiltrering og paginering.

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

Upload store filer (op til 5 GB) med multipart upload. AWS SDK håndterer dette automatisk:

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

Eller styr delene manuelt:

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-eksempel

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-eksempel

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

Konfigurer CORS (adgang via browser-SDK)

Hvis du kalder S3 API'et direkte fra browser-JavaScript (SPA, wallet-app, dashboard-værktøj), skal du konfigurere CORS på bucket'en først. Ellers blokerer browsere preflight-forespørgslen, og dine uploads fejler med No 'Access-Control-Allow-Origin' header is present.

Samme opbygning som AWS S3 — PutBucketCors / GetBucketCors / DeleteBucketCors-underressourcer:

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

Grænse og standardværdier

  • Op til 5 regler per bucket (specifikationen tillader 100; vi sætter grænsen ved 5 for at holde browserens preflight-svar kompakt).
  • Total konfiguration er begrænset til 64 KB serialiseret.
  • Hvis ingen CORS-konfiguration er sat, afvises browser-preflights — i overensstemmelse med AWS S3's standardholdning. Konfigurer eksplicitte regler for de oprindelser, du rent faktisk serverer fra.

Sikkerhedsnote fra den virkelige verden

CORS er et bekvemmelighedslag på browsersiden, ikke en sikkerhedsgrænse. Ethvert S3 API-kald kræver stadig en gyldig SigV4-signatur beregnet ud fra din API-nøgle — en tilladende CORS-konfiguration lader ikke hvem som helst bruge din bucket uden det legitimationsbevis. Det, CORS forhindrer: at en utilsigtet oprindelse (f.eks. en forældet kopi af din app på dev.myapp.com) sender signerede forespørgsler fra en browserkontekst.

Alternativ via dashboard

Filer-siden har en S3 CORS-post i hver mappes handlingsmenu. Samme underliggende lager; hvis du ikke ønsker at skrive PutBucketCors-kode, kan du konfigurere det der.

Forskelle fra Amazon S3

FunktionAmazon S3IPFS Ninja S3
LagringsmodelMuterbare objekterIndholdsadresseret (uforanderlige CID'er)
OverskrivningsadfærdErstatter objekt på stedetOpretter nyt CID, gammelt CID er stadig tilgængeligt
VersioneringUnderstøttetIkke understøttet (brug CID'er til versionering)
Server-side krypteringUnderstøttetIkke understøttet (indhold er på IPFS)
LivscykluspolitikkerUnderstøttetIkke understøttet
Bucket-politikker / ACLUnderstøttetBrug gateway-adgangstilstande
Forhåndssignerede URL'erUnderstøttetBrug signerede upload-tokens
Maks. objektstørrelse5 TB5 GB (multipart), 100 MB (enkelt PUT)
RegionerMulti-regionKun us-east-1
ETag-værdiMD5-hashIPFS CID
Ekstra headereStandard S3x-amz-meta-cid (IPFS CID)
CID-formatN/AModerne CIDv1 (bafy…) til nye uploads; ældre Qm… forbliver gyldigt som input
Bucket-navnerumGlobalt (AWS-bredt)Globalt (på tværs af alle IPFS Ninja-konti) — samme semantik
CORSPutBucketCors understøttetPutBucketCors understøttet (grænse på 5 regler)

Migrering fra Amazon S3

Erstat din S3-klientkonfiguration:

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

Dine eksisterende PutObject-, GetObject-, ListObjectsV2- og DeleteObject-kald fungerer uden ændringer.

Migrering fra Filebase

Erstat endpoint-URL'en:

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