· Nacho Coll · Tutorials  · 9 min czytania

IPFS Upload API — Kompletny tutorial dla deweloperów

Naucz się przesyłać pliki do IPFS przez REST API. Pełne przykłady kodu w JavaScript, Node.js i curl. Przesyłaj JSON, obrazy, używaj podpisanych tokenów do przesyłania po stronie klienta.

Naucz się przesyłać pliki do IPFS przez REST API. Pełne przykłady kodu w JavaScript, Node.js i curl. Przesyłaj JSON, obrazy, używaj podpisanych tokenów do przesyłania po stronie klienta.

IPFS Upload API — Kompletny tutorial dla deweloperów

Przesyłanie plików do IPFS powinno być tak proste, jak wysłanie żądania POST. W tym tutorialu zrobisz dokładnie to — prześlesz dokumenty JSON, obrazy i pliki PDF do IPFS używając tylko fetch() i klucza API. Na koniec będziesz mieć kompletny skrypt Node.js, który przesyła zawartość, wyświetla pliki, pobiera metadane i generuje podpisane tokeny do bezpiecznego przesyłania po stronie klienta. Nowy w IPFS? Zacznij od Co to jest IPFS Pinning?, aby zrozumieć podstawy przed zanurzeniem się w kod.

IPFS Ninja API keys management page

Co zbudujesz

  • Prześlij obiekt JSON do IPFS i otrzymaj identyfikator zawartości (CID).
  • Prześlij obraz binarny z dysku.
  • Dołącz opisy i niestandardowe metadane do przesyłanych plików.
  • Zapytaj o historię przesłanych plików według zakresu dat.
  • Pobierz szczegóły konkretnego pliku.
  • Utwórz podpisane tokeny z ograniczonym czasem, aby przeglądarka mogła przesyłać bezpośrednio bez ujawniania klucza API.
  • Obsługuj błędy i implementuj logikę ponawiania.

Wszystko działa w stosunku do jednego podstawowego URL: https://api.ipfs.ninja

1. Konfiguracja — Zarejestruj się i uzyskaj klucz API

  1. Zarejestruj się na bezpłatne konto (karta kredytowa nie jest wymagana).
  2. Przejdź do API Keys w pasku bocznym dashboardu.
  3. Kliknij Create key, nadaj mu nazwę i natychmiast skopiuj klucz — nie zostanie ponownie wyświetlony.
API Keys page — create and manage your keys

Twój klucz wygląda jak bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Każdy poniższy przykład wysyła go w nagłówku X-Api-Key.

2. Prześlij JSON do IPFS

Najprostszy upload: przekaż zwykły obiekt JavaScript jako content, a API zserializuje go, przypnie do IPFS i zwróci CID.

// upload-json.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

const payload = {
  content: {
    name: "Galactic Badge #42",
    description: "Proof of attendance — Galactic Meetup 2026",
    attributes: [
      { trait_type: "Event", value: "Galactic Meetup" },
      { trait_type: "Year", value: 2026 }
    ]
  }
};

const res = await fetch(`${API}/upload/new`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": API_KEY
  },
  body: JSON.stringify(payload)
});

const data = await res.json();
console.log("CID :", data.cid);
console.log("Size:", data.sizeMB, "MB");
console.log("IPFS:", data.uris.ipfs);
console.log("URL :", data.uris.url);

Uruchom za pomocą node upload-json.mjs. Pomyślna odpowiedź wygląda tak:

{
  "cid": "bafkreigx7gq...",
  "sizeMB": 0.0004,
  "uris": {
    "ipfs": "ipfs://bafkreigx7gq...",
    "url": "https://ipfs.ninja/ipfs/bafkreigx7gq..."
  }
}

Pole url wskazuje publiczną bramę HTTP, więc zawartość jest natychmiast dostępna w dowolnej przeglądarce.

3. Prześlij obraz

Pliki binarne (obrazy, PDF, audio) są wysyłane jako ciągi zakodowane w base64 w polu content.

// upload-image.mjs
import { readFileSync } from "node:fs";

const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

const imageBuffer = readFileSync("./photo.png");
const base64 = imageBuffer.toString("base64");

const res = await fetch(`${API}/upload/new`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": API_KEY
  },
  body: JSON.stringify({ content: base64 })
});

const data = await res.json();
console.log("Image CID:", data.cid);
console.log("Gateway  :", data.uris.url);

API automatycznie wykrywa typ MIME — PNG, JPEG, WebP, GIF i PDF są wszystkie obsługiwane. Nie są wymagane żadne dodatkowe nagłówki ani nadpisania content-type.

Z curl ta sama operacja wygląda tak:

BASE64=$(base64 -w 0 photo.png)

curl -X POST https://api.ipfs.ninja/upload/new \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: bws_your_key_here" \
  -d "{\"content\": \"$BASE64\"}"

4. Upload z metadanymi

Każdy upload akceptuje dwa opcjonalne pola: description (etykieta dowolnego tekstu) i metadata (dowolne pary klucz-wartość). Oba są przechowywane obok CID i zwracane, gdy później wyświetlasz lub pobierasz plik.

// upload-with-metadata.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

const res = await fetch(`${API}/upload/new`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": API_KEY
  },
  body: JSON.stringify({
    content: { title: "Meeting Notes", body: "Q1 roadmap recap..." },
    description: "Q1 2026 planning meeting notes",
    metadata: {
      project: "acme-app",
      author: "dana",
      version: "1"
    }
  })
});

const data = await res.json();
console.log("CID:", data.cid);

Metadane ułatwiają filtrowanie i organizowanie plików po Twojej stronie bez parsowania samej zawartości IPFS.

5. Przypnij istniejący CID

Jeśli masz już zawartość w IPFS i chcesz upewnić się, że pozostanie dostępna, przypnij ją za pomocą CID:

// pin-cid.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

const res = await fetch(`${API}/pin`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": API_KEY
  },
  body: JSON.stringify({
    cid: "bafkreigx7gq...",
    description: "Pinned from external source"
  })
});

const data = await res.json();
console.log("Pinned:", data.cid);

6. Wyświetl listę swoich plików

Pobierz każdy plik, który przesłałeś w okresie czasu. Parametry zapytania from i to to znaczniki czasu Unix w milisekundach.

// list-files.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

const now = Date.now();
const oneWeekAgo = now - 7 * 24 * 60 * 60 * 1000;

const url = `${API}/upload/list?from=${oneWeekAgo}&to=${now}`;

const res = await fetch(url, {
  headers: { "X-Api-Key": API_KEY }
});

const files = await res.json();

for (const file of files) {
  console.log(`${file.cid}  ${file.description ?? "(no description)"}`);
}

Z curl:

FROM=$(($(date +%s) * 1000 - 604800000))
TO=$(($(date +%s) * 1000))

curl -s "https://api.ipfs.ninja/upload/list?from=$FROM&to=$TO" \
  -H "X-Api-Key: bws_your_key_here" | jq .

7. Pobierz szczegóły pliku

Pobierz pełny rekord dla pojedynczego CID, w tym metadane, rozmiar i znaczniki czasu:

// get-file.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const CID = "bafkreigx7gq...";

const res = await fetch(`${API}/file/${CID}`, {
  headers: { "X-Api-Key": API_KEY }
});

const details = await res.json();
console.log(JSON.stringify(details, null, 2));

8. Przesyłanie po stronie klienta z podpisanymi tokenami

Osadzanie klucza API w pakiecie przeglądarki to ryzyko bezpieczeństwa. Zamiast tego wygeneruj krótkoterminowy podpisany token na swoim serwerze i przekaż go klientowi.

Serwer (Express)

// server.mjs
import express from "express";

const app = express();
const API = "https://api.ipfs.ninja";
const API_KEY = process.env.IPFS_API_KEY;

app.post("/api/upload-token", async (req, res) => {
  const response = await fetch(`${API}/upload/signed-url`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-Api-Key": API_KEY
    },
    body: JSON.stringify({
      name: "browser-upload",
      expiresIn: 600          // token valid for 10 minutes
    })
  });

  const { token, tokenId, expiresAt } = await response.json();
  res.json({ token, tokenId, expiresAt });
});

app.listen(3000, () => console.log("Server running on :3000"));

Klient przeglądarki

<!-- upload.html -->
<input type="file" id="filePicker" />
<button id="uploadBtn">Upload to IPFS</button>
<pre id="result"></pre>

<script>
  const API = "https://api.ipfs.ninja";

  document.getElementById("uploadBtn").addEventListener("click", async () => {
    // 1. Get a signed token from your own backend
    const tokenRes = await fetch("/api/upload-token", { method: "POST" });
    const { token } = await tokenRes.json();

    // 2. Read the selected file as base64
    const file = document.getElementById("filePicker").files[0];
    if (!file) return alert("Pick a file first");

    const base64 = await new Promise((resolve) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result.split(",")[1]);
      reader.readAsDataURL(file);
    });

    // 3. Upload directly to IPFS using the signed token
    const uploadRes = await fetch(`${API}/upload/new`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Signed ${token}`
      },
      body: JSON.stringify({
        content: base64,
        description: file.name
      })
    });

    const data = await uploadRes.json();
    document.getElementById("result").textContent = JSON.stringify(data, null, 2);
  });
</script>

Przeglądarka nigdy nie widzi Twojego klucza API. Podpisany token wygasa automatycznie. Tokeny są wielokrotnego użytku — można ich używać wielokrotnie, dopóki nie wygasną lub nie zostaną unieważnione. useCount jest śledzony, ale nie jest egzekwowany jako limit.

9. Obsługa błędów

API używa konwencjonalnych kodów stanu HTTP. Oto te, które powinieneś obsługiwać jawnie:

StatusZnaczenieCo zrobić
400Bad request — brakujące lub nieprawidłowe polaSprawdź, czy content istnieje i jest prawidłowy
401Unauthorized — zły lub brakujący klucz APIZweryfikuj nagłówek X-Api-Key
413Payload za dużyZmniejsz rozmiar pliku lub podziel zawartość
429Ograniczenie częstotliwościWycofaj się i spróbuj ponownie z wykładniczym opóźnieniem
500Błąd serweraSpróbuj ponownie po krótkim opóźnieniu

Odporna funkcja uploadu z wykładniczym backoff:

// resilient-upload.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

async function uploadWithRetry(content, retries = 3) {
  for (let attempt = 1; attempt <= retries; attempt++) {
    const res = await fetch(`${API}/upload/new`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Api-Key": API_KEY
      },
      body: JSON.stringify({ content })
    });

    if (res.ok) return await res.json();

    const body = await res.text();

    if (res.status === 401) {
      throw new Error(`Authentication failed: ${body}`);
    }

    if (res.status === 413) {
      throw new Error(`Payload too large — reduce file size. ${body}`);
    }

    if (res.status === 429 || res.status >= 500) {
      const delay = Math.pow(2, attempt) * 1000;    // 2s, 4s, 8s
      console.warn(`Attempt ${attempt} failed (${res.status}). Retrying in ${delay}ms...`);
      await new Promise((r) => setTimeout(r, delay));
      continue;
    }

    throw new Error(`Upload failed (${res.status}): ${body}`);
  }

  throw new Error("Upload failed after all retries");
}

// Usage
const data = await uploadWithRetry({ hello: "world" });
console.log("CID:", data.cid);

10. Pełny działający przykład

Pojedynczy skrypt, który ćwiczy każdy endpoint omówiony w tym tutorialu. Zapisz go jako ipfs-demo.mjs i uruchom za pomocą node ipfs-demo.mjs.

// ipfs-demo.mjs
import { readFileSync } from "node:fs";

const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";

const headers = {
  "Content-Type": "application/json",
  "X-Api-Key": API_KEY
};

async function request(method, path, body) {
  const opts = { method, headers };
  if (body) opts.body = JSON.stringify(body);
  const res = await fetch(`${API}${path}`, opts);
  if (!res.ok) throw new Error(`${method} ${path} → ${res.status}: ${await res.text()}`);
  return res.json();
}

// --- 1. Upload JSON ---
console.log("--- Upload JSON ---");
const jsonResult = await request("POST", "/upload/new", {
  content: { name: "Demo Token", edition: 1 },
  description: "Tutorial demo — JSON upload",
  metadata: { tutorial: "true" }
});
console.log("CID:", jsonResult.cid);
console.log("URL:", jsonResult.uris.url);

// --- 2. Upload an image (if photo.png exists) ---
try {
  const img = readFileSync("./photo.png");
  console.log("\n--- Upload Image ---");
  const imgResult = await request("POST", "/upload/new", {
    content: img.toString("base64"),
    description: "Tutorial demo — image upload"
  });
  console.log("CID:", imgResult.cid);
  console.log("URL:", imgResult.uris.url);
} catch {
  console.log("\n--- Skipping image upload (no photo.png found) ---");
}

// --- 3. Pin the JSON CID ---
console.log("\n--- Pin CID ---");
const pinResult = await request("POST", "/pin", {
  cid: jsonResult.cid,
  description: "Pinned from tutorial"
});
console.log("Pinned:", pinResult.cid);

// --- 4. Get file details ---
console.log("\n--- File Details ---");
const details = await request("GET", `/file/${jsonResult.cid}`);
console.log(JSON.stringify(details, null, 2));

// --- 5. List recent files ---
console.log("\n--- Recent Files ---");
const now = Date.now();
const oneHourAgo = now - 60 * 60 * 1000;
const files = await request("GET", `/upload/list?from=${oneHourAgo}&to=${now}`);
console.log(`Found ${files.length} file(s) in the last hour`);
for (const f of files) {
  console.log(` - ${f.cid}  ${f.description ?? ""}`);
}

// --- 6. Create a signed upload token ---
console.log("\n--- Signed Token ---");
const tokenResult = await request("POST", "/upload/signed-url", {
  name: "demo-token",
  expiresIn: 300
});
console.log("Token ID :", tokenResult.tokenId);
console.log("Expires  :", new Date(tokenResult.expiresAt).toISOString());

// --- 7. Upload using the signed token ---
console.log("\n--- Upload with Signed Token ---");
const signedRes = await fetch(`${API}/upload/new`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Signed ${tokenResult.token}`
  },
  body: JSON.stringify({
    content: { note: "Uploaded with a signed token" }
  })
});
const signedData = await signedRes.json();
console.log("CID:", signedData.cid);

console.log("\nDone.");

Zastąp bws_your_key_here prawdziwym kluczem i uruchom skrypt. Każdy krok drukuje swój wynik, więc możesz śledzić.

11. Następne kroki

Teraz wiesz, jak przesyłać, przypinać, wyświetlać listy i pobierać pliki przez IPFS Upload API oraz jak zachować bezpieczeństwo uploadów z przeglądarki za pomocą podpisanych tokenów. Aby uzyskać szerszy przegląd, w tym UI dashboardu i przykłady Pythona, zobacz Jak przesyłać pliki do IPFS. Oto, dokąd dalej:

  • Dokumentacja API — Pełna dokumentacja endpointów na ipfs.ninja/docs.
  • Niestandardowe bramy — Serwuj zawartość IPFS ze swojej własnej domeny. Zobacz przewodnik konfiguracji bramy.
  • Analityka — Śledź wolumen uploadu, przepustowość i liczbę przypięć w dashboardzie.
  • Klient HTTP — Nie jest wymagany SDK. Możesz używać standardowego fetch() lub dowolnego klienta HTTP do interakcji z API.

Jeśli napotkasz problemy, otwórz zgłoszenie na support.ipfs.ninja lub dołącz do społeczności na Discord.

Wróć do Bloga

Powiązane Artykuły

Zobacz Wszystkie Artykuły »