· Nacho Coll · Tutorials · 9 min skaitymo
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.

IPFS Upload API — Pilnas vadovas kūrėjams
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ą.

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ą
- Užsiregistruokite nemokamai paskyrai (kredito kortelės nereikia).
- Eikite į API Keys valdymo skydelio šoninėje juostoje.
- Spustelėkite Create key, suteikite jam pavadinimą ir iškart nukopijuokite raktą — jis nebus parodytas dar kartą.

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ūsena | Reikšmė | Ką daryti |
|---|---|---|
| 400 | Bad request — trūkstami arba negaliojantys laukai | Patikrinkite, ar content yra ir galioja |
| 401 | Unauthorized — neteisingas arba nesantys API raktas | Patikrinkite antraštę X-Api-Key |
| 413 | Payload too large | Sumažinkite failo dydį arba padalinkite turinį |
| 429 | Rate limited | Palaukite ir pabandykite dar kartą su eksponentine delsa |
| 500 | Server error | Bandykite 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.
