IPFS Upload API — Pilnas vadovas kūrėjams

Išmokite įkelti failus į IPFS per REST API. Pilni kodo pavyzdžiai JavaScript, Node.js ir curl. Įkelkite JSON, vaizdus, naudokite pasirašytus žetonus kliento pusės įkėlimams.

Nacho CollAutorius Atnaujinta: 9 min skaitymo
Išmokite įkelti failus į IPFS per REST API. Pilni kodo pavyzdžiai JavaScript, Node.js ir curl. Įkelkite JSON, vaizdus, naudokite pasirašytus žetonus kliento pusės įkėlimams.
TL;DR
  • Įkelkite JSON, vaizdus ir PDF failus į IPFS vienu POST užklausos ir API rakto deriniu.
  • Sugeneruokite pasirašytus, laiko ribojamus tokenus, kad kliento pusės programėlės galėtų įkelti failus neatskleisdamos jūsų API rakto.
  • Užklauskite įkėlimų istoriją pagal datų intervalą ir gaukite bet kurio anksčiau įkelto failo metaduomenis.
  • Kiekvienas įkėlimas vyksta per vieną bazinį URL — jokiai kalbai nereikia diegti SDK.

Failų įkėlimas į IPFS turėtų būti toks paprastas, kaip POST užklausos siuntimas. Šiame vadove darysite būtent tai — įkelsite JSON dokumentus, vaizdus ir PDF failus į IPFS naudodami nieko daugiau, tik fetch() ir API raktą. Pabaigoje turėsite pilną Node.js skriptą, kuris įkelia turinį, išvardija failus, gauna metaduomenis ir generuoja pasirašytus žetonus saugiems kliento pusės įkėlimams. Naujas IPFS? Pradėkite nuo Kas yra IPFS Pinning?, kad suprastumėte pagrindus prieš nardami į kodą.

IPFS Ninja API keys management page

Ką sukursite#

  • Įkelti JSON objektą į IPFS ir gauti turinio identifikatorių (CID).
  • Įkelti dvejetainį vaizdą iš disko.
  • Pridėti aprašymus ir pasirinktinius metaduomenis prie įkėlimų.
  • Užklausti įkėlimų istoriją pagal datos diapazoną.
  • Gauti detales apie konkretų failą.
  • Sukurti laiku apribotus pasirašytus žetonus, kad naršyklė galėtų įkelti tiesiogiai, neatverdama jūsų API rakto.
  • Tvarkyti klaidas ir įgyvendinti pakartotinio bandymo logiką.

Visa tai veikia prieš vieną pagrindinį URL: https://api.ipfs.ninja

1. Sąranka — Užsiregistruokite ir gaukite API raktą#

  1. Užsiregistruokite nemokamai paskyrai (kredito kortelės nereikia).
  2. Eikite į API Keys valdymo skydelio šoninėje juostoje.
  3. Spustelėkite Create key, suteikite jam pavadinimą ir iškart nukopijuokite raktą — jis nebus parodytas dar kartą.
API Keys page — create and manage your keys

Jūsų raktas atrodo taip: bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Kiekvienas toliau pateiktas pavyzdys siunčia jį antraštėje X-Api-Key.

2. JSON įkėlimas į IPFS#

Paprasčiausias įkėlimas: perduokite paprastą JavaScript objektą kaip content ir API jį serializuos, prisegs prie IPFS ir grąžins 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);

Paleiskite su node upload-json.mjs. Sėkmingas atsakymas atrodo taip:

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

Laukas url nurodo viešą HTTP vartą, todėl turinys yra iškart pasiekiamas bet kurioje naršyklėje.

3. Vaizdo įkėlimas#

Dvejetainiai failai (vaizdai, PDF, garsas) siunčiami kaip base64 koduotos eilutės lauke 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 automatiškai aptinka MIME tipą — PNG, JPEG, WebP, GIF ir PDF visi palaikomi. Papildomų antraščių ar content-type perrašymų nereikia.

Su curl ta pati operacija atrodo taip:

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. Įkėlimas su metaduomenimis#

Kiekvienas įkėlimas priima du neprivalomus laukus: description (laisvo teksto etiketė) ir metadata (savavališkos rakto-reikšmės poros). Abu saugomi šalia CID ir grąžinami, kai vėliau išvardijate ar gaunate failą.

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

Metaduomenys palengvina failų filtravimą ir organizavimą jūsų pusėje neanalizuojant paties IPFS turinio.

5. Esamo CID prisegimas#

Jei jau turite turinį IPFS ir norite užtikrinti, kad jis liks prieinamas, prisekite jį pagal 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. Jūsų failų sąrašas#

Gaukite visus failus, kuriuos įkėlėte per laiko langą. Užklausos parametrai from ir to yra Unix laiko žymos milisekundėmis.

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

Su 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. Failo detalės#

Gaukite pilną įrašą apie vieną CID, įskaitant metaduomenis, dydį ir laiko žymas:

// 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. Kliento pusės įkėlimai su pasirašytais žetonais#

API rakto įdėjimas į naršyklės paketą yra saugumo rizika. Vietoj to, savo serveryje sukurkite trumpalaikį pasirašytą žetoną ir perduokite jį klientui.

Serveris (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"));

Naršyklės klientas#

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

Naršyklė niekada nemato jūsų API rakto. Pasirašytas žetonas automatiškai baigia galioti. Žetonai yra kelis kartus naudojami — juos galima naudoti kelis kartus, kol jie nesibaigia arba neatšaukiami. useCount stebimas, bet netaikomas kaip limitas.

9. Klaidų tvarkymas#

API naudoja įprastinius HTTP būsenos kodus. Štai tie, kuriuos turėtumėte tvarkyti aiškiai:

BūsenaReikšmėKą daryti
400Bad request — trūkstami arba negaliojantys laukaiPatikrinkite, ar content yra ir galioja
401Unauthorized — neteisingas arba nesantys API raktasPatikrinkite antraštę X-Api-Key
413Payload too largeSumažinkite failo dydį arba padalinkite turinį
429Rate limitedPalaukite ir pabandykite dar kartą su eksponentine delsa
500Server errorBandykite dar kartą po trumpos delsos

Atspari įkėlimo funkcija su eksponentiniu 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. Pilnas darbingas pavyzdys#

Vienas skriptas, kuris išbando kiekvieną šiame vadove aptartą endpoint. Išsaugokite jį kaip ipfs-demo.mjs ir paleiskite su 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.");

Pakeiskite bws_your_key_here tikru raktu ir paleiskite skriptą. Kiekvienas žingsnis išspausdina savo rezultatą, kad galėtumėte sekti.

11. Tolesni žingsniai#

Dabar žinote, kaip įkelti, prisegti, išvardinti ir gauti failus per IPFS Upload API ir kaip apsaugoti naršyklės įkėlimus pasirašytais žetonais. Platesniam apžvalgai, įskaitant valdymo skydelio UI ir Python pavyzdžius, žiūrėkite Kaip įkelti failus į IPFS. Štai kur eiti iš čia:

  • API Reference — Pilna endpoint dokumentacija ipfs.ninja/docs.
  • Pasirinktiniai vartai — Aptarnaukite IPFS turinį iš savo paties domeno. Žiūrėkite vartų sąrankos vadovą.
  • Analitika — Sekite įkėlimų apimtį, pralaidumą ir prisegimų skaičių valdymo skydelyje.
  • HTTP klientas — SDK nereikia. Galite naudoti standartinį fetch() arba bet kurį HTTP klientą sąveikai su API.

Jei susidursite su problemomis, atidarykite tikietą support.ipfs.ninja arba prisijunkite prie bendruomenės Discord. Jei ateinate iš Filebase, mūsų Filebase alternatyvos vadovas paaiškina įkėlimo API skirtumus.

Išsamų NFT metaduomenų struktūros ir ERC-721 tokenURI šablonų vadovą rasite mūsų NFT metaduomenų saugojimo vadove.

Nacho Coll

Apie autorių

Founder & Engineer at IPFS.NINJA

Nacho founded IPFS.NINJA to make content-addressed storage feel as simple as an S3 PUT — a single API call, a permanent CID, no wallets or peer discovery to reason about. Writes about IPFS internals, decentralized storage patterns, and the pinning-service landscape from the operator side of the wire.

Grįžti į Tinklaraštį

Susiję straipsniai