· Nacho Coll · Tutorials · 14 分钟阅读
如何在 2026 年将文件上传到 IPFS — 完整指南
了解如何使用仪表板、REST API、JavaScript 或 Python 将 JSON、图片、PDF 和任何文件上传到 IPFS。带代码示例的分步指南。

如何在 2026 年将文件上传到 IPFS — 完整指南
如果您曾经希望以一种没有任何单一公司可以控制、任何人都可以验证、并且抵抗审查的方式存储文件,那么星际文件系统(InterPlanetary File System,IPFS)就是答案。本指南将引导您了解将文件上传到 IPFS 的每一种实用方法——从简单的拖放仪表板到 JavaScript 和 Python 中可用于生产的代码。

什么是 IPFS,为什么要使用它?
IPFS 是一种用于存储和共享文件的对等协议。IPFS 不是按内容所在的位置(特定服务器上的 URL)来寻址内容,而是按内容是什么来寻址。每个文件都会获得一个独特的内容标识符(CID),该标识符源自其内容的加密哈希。这种设计为您提供了传统托管无法匹敌的三个特性:
- 内容寻址。CID 保证您收到的数据正是上传的数据。如果有一个字节发生变化,CID 就会变化。任何人都无法在不使其地址失效的情况下篡改您的文件。
- 永久性。只要网络上至少有一个节点固定(pin)了您的文件,它就会保持可用。像 IPFS Ninja 这样的固定服务可以确保您的文件保持在线,而无需您运行自己的基础设施。要了解为什么固定很重要以及垃圾回收的工作原理,请参阅什么是 IPFS 固定?。
- 抗审查。IPFS 上的文件不绑定到单个域名或服务器。没有政府或公司可以关闭的单点故障。
常见的用例包括 NFT 元数据和媒体、去中心化应用程序资产、科学数据集、公共记录,以及任何数据完整性至关重要的场景。
前提条件
在上传任何内容之前,您需要两样东西:
一个 IPFS Ninja 账户。在 https://ipfs.ninja/signup 免费注册。免费计划为您提供 500 个文件和 1 GB 的存储空间——绰绰有余足以开始。
一个 API 密钥。登录后,进入仪表板中的 API Keys 部分并生成一个新密钥。它看起来像
bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6(前缀bws_a1b2c3d4显示在仪表板中以便识别)。请保密此密钥。您需要在每个 API 请求中将其传递到X-Api-Key标头中。
如果您只想使用 Web 仪表板,可以跳过 API 密钥步骤,但拥有 API 密钥可以让您从自己的应用程序中进行编程上传。
方法 1:Web 仪表板(拖放)
上传文件最快的方法是通过 IPFS Ninja 仪表板。
- 导航到 https://ipfs.ninja/upload 并登录。
- 将任何文件——JSON、PNG、JPEG、PDF、SVG 或任何其他类型——拖放到上传区域,或点击浏览文件系统。
- 可选添加描述和元数据(键值对)以帮助您稍后整理文件。
- 点击上传。几秒钟内,您的文件就会被固定到 IPFS,您将收到一个 CID 和一个网关 URL。
此方法支持任何文件类型,无需代码。它非常适合一次性上传、快速测试或需要固定内容的非技术团队成员。
方法 2:使用 curl 的 REST API
对于自动化和脚本,REST API 是最直接的方法。端点为:
POST https://api.ipfs.ninja/upload/new每个请求都需要 X-Api-Key 标头和带有 content 字段的 JSON 主体。
上传 JSON
要上传 JSON 对象,请直接将其作为 content 的值传递:
curl -X POST https://api.ipfs.ninja/upload/new \
-H "Content-Type: application/json" \
-H "X-Api-Key: bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
-d '{
"content": {
"name": "Astro Cat #42",
"description": "A fearless cat exploring the cosmos.",
"image": "ipfs://bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm",
"attributes": [
{ "trait_type": "Background", "value": "Nebula" },
{ "trait_type": "Helmet", "value": "Gold" }
]
},
"description": "NFT metadata for Astro Cat #42",
"metadata": { "collection": "astro-cats", "tokenId": "42" }
}'description 和 metadata 字段是可选的。它们与您的文件一起存储在 IPFS Ninja 仪表板和 API 响应中,以帮助您稍后识别和过滤上传。它们不包含在固定到 IPFS 的内容中。
上传图片(二进制文件)
对于图片或 PDF 等二进制文件,请对文件进行 base64 编码,并将编码后的字符串作为 content 传递:
curl -X POST https://api.ipfs.ninja/upload/new \
-H "Content-Type: application/json" \
-H "X-Api-Key: bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
-d "{
\"content\": \"$(base64 -w 0 photo.png)\",
\"description\": \"Product photo for landing page\",
\"metadata\": { \"project\": \"website-redesign\" }
}"API 会自动检测内容类型。无需指定您要上传的是 JSON、图片还是 PDF——服务会为您处理。
方法 3:JavaScript / Node.js
使用内置的 fetch API(Node.js 18+ 或任何现代浏览器),上传到 IPFS 只需几行代码。
上传 JSON
const API_KEY = "bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6";
const metadata = {
name: "Astro Cat #42",
description: "A fearless cat exploring the cosmos.",
image: "ipfs://bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm",
attributes: [
{ trait_type: "Background", value: "Nebula" },
{ trait_type: "Helmet", value: "Gold" },
],
};
const response = await fetch("https://api.ipfs.ninja/upload/new", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY,
},
body: JSON.stringify({
content: metadata,
description: "NFT metadata for Astro Cat #42",
}),
});
const result = await response.json();
console.log("CID:", result.cid);
console.log("Gateway URL:", result.uris.url);上传二进制文件
import { readFileSync } from "node:fs";
const API_KEY = "bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6";
const fileBuffer = readFileSync("photo.png");
const base64Content = fileBuffer.toString("base64");
const response = await fetch("https://api.ipfs.ninja/upload/new", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY,
},
body: JSON.stringify({
content: base64Content,
description: "Product photo",
metadata: { project: "website-redesign" },
}),
});
const result = await response.json();
console.log("CID:", result.cid);
console.log("IPFS URI:", result.uris.ipfs);
console.log("Gateway URL:", result.uris.url);带错误处理的批量上传
在生产环境中,您经常需要上传许多文件。这是一个带有重试的可重用助手:
import { readFileSync } from "node:fs";
const API_KEY = "bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6";
const API_URL = "https://api.ipfs.ninja/upload/new";
async function uploadToIPFS(content, options = {}) {
const body = { content };
if (options.description) body.description = options.description;
if (options.metadata) body.metadata = options.metadata;
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY,
},
body: JSON.stringify(body),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Upload failed (${response.status}): ${error}`);
}
return response.json();
}
// Upload JSON
const jsonResult = await uploadToIPFS(
{ name: "My Data", values: [1, 2, 3] },
{ description: "Sample dataset" }
);
// Upload image
const imageBase64 = readFileSync("banner.jpg").toString("base64");
const imageResult = await uploadToIPFS(imageBase64, {
description: "Banner image",
metadata: { format: "jpg", width: "1200" },
});
console.log("JSON CID:", jsonResult.cid);
console.log("Image CID:", imageResult.cid);方法 4:Python
Python 的 requests 库使 IPFS 上传变得简单。
上传 JSON
import requests
API_KEY = "bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
API_URL = "https://api.ipfs.ninja/upload/new"
headers = {
"Content-Type": "application/json",
"X-Api-Key": API_KEY,
}
payload = {
"content": {
"name": "Astro Cat #42",
"description": "A fearless cat exploring the cosmos.",
"image": "ipfs://bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm",
"attributes": [
{"trait_type": "Background", "value": "Nebula"},
{"trait_type": "Helmet", "value": "Gold"},
],
},
"description": "NFT metadata for Astro Cat #42",
"metadata": {"collection": "astro-cats", "tokenId": "42"},
}
response = requests.post(API_URL, json=payload, headers=headers)
result = response.json()
print(f"CID: {result['cid']}")
print(f"Gateway URL: {result['uris']['url']}")上传二进制文件
import base64
import requests
API_KEY = "bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
API_URL = "https://api.ipfs.ninja/upload/new"
headers = {
"Content-Type": "application/json",
"X-Api-Key": API_KEY,
}
with open("photo.png", "rb") as f:
encoded = base64.b64encode(f.read()).decode("utf-8")
payload = {
"content": encoded,
"description": "Product photo",
"metadata": {"project": "website-redesign"},
}
response = requests.post(API_URL, json=payload, headers=headers)
result = response.json()
print(f"CID: {result['cid']}")
print(f"Size: {result['sizeMB']} MB")
print(f"IPFS URI: {result['uris']['ipfs']}")
print(f"Gateway URL: {result['uris']['url']}")批量上传
import base64
from pathlib import Path
import requests
API_KEY = "bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
API_URL = "https://api.ipfs.ninja/upload/new"
HEADERS = {"Content-Type": "application/json", "X-Api-Key": API_KEY}
def upload_file(file_path, description=None, metadata=None):
with open(file_path, "rb") as f:
encoded = base64.b64encode(f.read()).decode("utf-8")
payload = {"content": encoded}
if description:
payload["description"] = description
if metadata:
payload["metadata"] = metadata
response = requests.post(API_URL, json=payload, headers=HEADERS)
response.raise_for_status()
return response.json()
# Upload all PNGs in a directory
for png in Path("./images").glob("*.png"):
result = upload_file(png, description=f"Image: {png.name}")
print(f"{png.name} -> {result['cid']}")理解响应
每次成功上传都会返回一个 JSON 对象,其字段如下:
{
"cid": "bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm",
"sizeMB": 0.024,
"uris": {
"ipfs": "ipfs://bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm",
"url": "https://ipfs.ninja/ipfs/bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm"
}
}| 字段 | 描述 |
|---|---|
cid | 内容标识符——您文件内容的唯一哈希。这是您文件在 IPFS 上的永久地址。 |
sizeMB | 已上传文件的大小(以兆字节为单位)。 |
uris.ipfs | IPFS 原生 URI(ipfs://CID)。从智能合约、NFT 元数据或其他 IPFS 感知应用程序引用文件时使用此项。 |
uris.url | 您可以在任何浏览器中打开的直接 HTTPS 网关 URL。非常适合共享、嵌入到网站或快速验证。 |
访问您的文件
文件固定后,有两种主要的检索方式。
专用网关
每个 IPFS Ninja 账户都包括一个带有自定义 slug 的专用网关:
https://your-slug.gw.ipfs.ninja/ipfs/{CID}专用网关比公共网关更快、更可靠,因为它们直接连接到 IPFS Ninja 固定基础设施。您可以使用上传响应中的 CID 通过您的专用网关访问您的文件。
公共 IPFS 网关
任何 IPFS 网关都可以使用 CID 提供您的内容:
https://ipfs.ninja/ipfs/{CID} ← 您的专用网关
https://dweb.link/ipfs/{CID} ← 公共网关
https://w3s.link/ipfs/{CID} ← 公共网关当您想要验证您的内容是否可以从 IPFS Ninja 网络外部访问时,公共网关非常有用。请记住,与您的专用网关相比,它们可能更慢或受到速率限制。
从智能合约和 dApp
在链上存储引用时(例如在 ERC-721 令牌 URI 中),使用 ipfs:// URI:
ipfs://bafkreigh2akiscaildc7lqnpfuh3sksq4ogrtz7tpk2aulid5fhqotmqm钱包、市场和其他 IPFS 感知应用程序知道如何通过任何可用的网关解析此 URI。
最佳实践
将单个文件保持在 100 MB 以下。虽然 API 接受较大的上传,但较小的文件固定更快,并在 IPFS 网络上更有效地复制。如果您要处理大型数据集,请将它们拆分为较小的块。
使用描述性元数据。description 和 metadata 字段是免费的,并且使您稍后更容易管理上传。包括项目名称、版本号或任何有助于您搜索和过滤的标识符。
在您自己的数据库中存储 CID。即使 IPFS Ninja 存储您的上传历史记录,维护您自己的 CID 到应用程序级标识符(用户 ID、订单号、令牌 ID)的映射也使您的集成更具弹性。
在链上引用中使用 IPFS URI。在智能合约或不可变记录中始终存储 ipfs://CID 而不是 HTTPS 网关 URL。网关 URL 可能会改变;CID 不会。
对于结构化数据,首选 JSON 内容。当您的数据是结构化的(元数据、配置、记录)时,请将其作为 JSON 对象传递,而不是将其编码为字符串。API 存储得更有效,并且生成的 IPFS 内容是人类可读的。
优雅地处理错误。检查 HTTP 状态码并对 5xx 响应实施带有指数退避的重试。API 为 4xx 响应(无效的 API 密钥、缺少内容、信用不足)返回明确的错误消息,您应该将这些消息呈现给用户。
结论
将文件上传到 IPFS 从未如此简单。无论您喜欢可视化仪表板、快速 curl 命令,还是 JavaScript 或 Python 中的生产级集成,IPFS Ninja 都为您提供单一端点和跨所有内容类型的一致体验。
免费的 Dharma 计划包括 50 个文件、1 GB 存储空间和每月 2 GB 带宽——足以端到端构建和测试您的集成。当您准备扩展时,Bodhi 计划每月 5 美元、Karma 计划每月 19 美元和 Nirvana 计划每月 59 美元提供更高的限制、专用网关,以及(Nirvana 上的)优先支持。
创建您的免费账户 并在不到一分钟内开始将文件上传到 IPFS。
要深入了解带有签名令牌和客户端上传的 API,请参阅我们的 IPFS 上传 API 教程。有关包括列出文件、管理 API 密钥和配置网关的完整 API 参考,请访问文档。

