Español (ES)
Español (ES)
Appearance
Español (ES)
Español (ES)
Appearance
Usa el AWS SDK para subir, descargar y gestionar archivos en IPFS Ninja con el mismo código que usas para Amazon S3.
https://s3.ipfs.ninjaLa API S3 utiliza tu clave API de IPFS Ninja para la autenticación. Tu clave API sirve tanto como access key como secret key.
Tu clave tiene este formato:
bws_628bba35e9e0079d9ff9c392b1b55a7b
├──────────┘└──────────────────────────┘
prefix (12 chars) rest of key| Parámetro AWS | Valor | Ejemplo |
|---|---|---|
accessKeyId | Primeros 12 caracteres de tu clave API | bws_628bba35 |
secretAccessKey | La clave API completa (los 36 caracteres) | bws_628bba35e9e0079d9ff9c392b1b55a7b |
region | Siempre us-east-1 | us-east-1 |
WARNING
La clave API completa solo se muestra una vez al crearla. Si la pierdes, elimina la clave y crea una nueva desde la página de API Keys.
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: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdiLos buckets de S3 corresponden a tus carpetas de IPFS Ninja. Cuando subes un archivo a un bucket, se almacena en la carpeta correspondiente. Cuando listas los objetos de un bucket, ves los archivos de esa carpeta.
| Operación S3 | Equivalente en IPFS Ninja |
|---|---|
CreateBucket | Crear una nueva carpeta |
ListBuckets | Listar tus carpetas |
DeleteBucket | Eliminar una carpeta y todos sus archivos |
PutObject en bucket | Subir archivo a la carpeta |
ListObjectsV2 en bucket | Listar archivos en la carpeta |
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
Las carpetas creadas a través de la API S3 son las mismas carpetas visibles en tu Dashboard. Puedes organizar archivos desde la API S3, la API REST o la interfaz web — todas comparten el mismo sistema de carpetas.
INFO
A diferencia de Amazon S3, las carpetas de IPFS Ninja son planas por defecto. Para crear estructuras anidadas, usa los endpoints de carpetas de la API REST con parentFolderId. Desde la API S3, usa prefijos de clave (por ejemplo, images/photo.png) para organizar dentro de una carpeta.
Los nombres de bucket viven en un espacio de nombres global compartido por todos los clientes, igual que la semántica de AWS S3. Esto significa que:
CreateBucket con el mismo nombre desde cualquier cuenta devuelven BucketAlreadyExists (409).BucketAlreadyOwnedByYou (409).Si el nombre que quieres ya está en uso, elige uno con un ámbito distinto (myapp-photos-2026, acme-nft-metadata) — la misma convención que usarías en Amazon S3.
Sube un archivo a IPFS. El archivo se fija, se escanea por seguridad, y el CID se devuelve en los encabezados ETag y x-amz-meta-cid.
Para importar un archivo CAR en lugar de un archivo normal, añade el encabezado de metadato x-amz-meta-import: car. Consulta Importación CAR para más detalles.
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);# 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"Descarga un archivo por su clave (nombre de archivo) o CID.
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);Obtiene los metadatos de un archivo sin descargar el contenido.
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);Elimina el pin de un archivo de IPFS y lo borra de tu cuenta.
import { DeleteObjectCommand } from "@aws-sdk/client-s3";
await s3.send(new DeleteObjectCommand({
Bucket: "my-project",
Key: "photo.png"
}));Lista los archivos de un bucket con filtrado opcional por prefijo y paginación.
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
}Sube archivos grandes (hasta 5 GB) usando multipart upload. El AWS SDK lo gestiona automáticamente:
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 las partes manualmente:
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 }]
}
}));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())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!")
}Si llamas a la API S3 directamente desde JavaScript en el navegador (SPA, wallet app, herramienta del dashboard), necesitas configurar CORS en el bucket primero. De lo contrario, los navegadores bloquean el preflight y tus subidas fallan con No 'Access-Control-Allow-Origin' header is present.
Misma estructura que AWS S3 — subrecursos PutBucketCors / GetBucketCors / DeleteBucketCors:
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,
}],
},
}));import { GetBucketCorsCommand } from "@aws-sdk/client-s3";
const { CORSRules } = await s3.send(new GetBucketCorsCommand({ Bucket: "my-bucket" }));
console.log(CORSRules);import { DeleteBucketCorsCommand } from "@aws-sdk/client-s3";
await s3.send(new DeleteBucketCorsCommand({ Bucket: "my-bucket" }));CORS es una capa de conveniencia del lado del navegador, no un límite de seguridad. Cada llamada a la API S3 sigue requiriendo una firma SigV4 válida calculada a partir de tu clave API — una configuración CORS permisiva no permite que cualquiera use tu bucket sin esa credencial. Lo que CORS sí evita: que un origen no deseado (por ejemplo, una copia obsoleta de tu app en dev.myapp.com) envíe solicitudes firmadas desde un contexto de navegador.
La página de Archivos tiene una opción S3 CORS en el menú de acciones de cada carpeta. Es el mismo almacenamiento subyacente; si no quieres escribir código con PutBucketCors, configúralo ahí.
| Característica | Amazon S3 | IPFS Ninja S3 |
|---|---|---|
| Modelo de almacenamiento | Objetos mutables | Direccionamiento por contenido (CIDs inmutables) |
| Comportamiento al sobrescribir | Reemplaza el objeto en el sitio | Crea un nuevo CID, el CID anterior sigue accesible |
| Versionado | Soportado | No soportado (usa CIDs para versionar) |
| Cifrado del lado del servidor | Soportado | No soportado (el contenido está en IPFS) |
| Políticas de ciclo de vida | Soportadas | No soportadas |
| Políticas de bucket / ACLs | Soportadas | Usa modos de acceso del gateway |
| URLs prefirmadas | Soportadas | Usa tokens de subida firmados |
| Tamaño máximo de objeto | 5 TB | 5 GB (multipart), 100 MB (PUT individual) |
| Regiones | Multi-region | Solo us-east-1 |
Valor de ETag | Hash MD5 | IPFS CID |
| Headers adicionales | S3 estándar | x-amz-meta-cid (IPFS CID) |
| Formato de CID | N/D | CIDv1 moderno (bafy…) para nuevas subidas; el Qm… heredado sigue siendo válido como entrada |
| Espacio de nombres de bucket | Global (en todo AWS) | Global (en todas las cuentas de IPFS Ninja) — misma semántica |
| CORS | PutBucketCors soportado | PutBucketCors soportado (límite de 5 reglas) |
Reemplaza la configuración de tu cliente S3:
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
});Tus llamadas existentes a PutObject, GetObject, ListObjectsV2 y DeleteObject funcionan sin cambios.
Reemplaza la URL del endpoint:
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
});