· Nacho Coll · Guides · 12 分钟阅读
IPFS CID 详解:它是什么以及内容寻址如何工作
对 IPFS Content Identifier (CID) 的清晰技术解释。内容寻址如何工作、CID 版本,以及创建你的第一个 CID。

如果你接触过 IPFS (InterPlanetary File System),很可能见过形如 QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG 或 bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi 的字符串。它们并非随机乱码 —— 它们是 Content Identifier (CID),IPFS 内容寻址系统的核心支柱。
理解 CID 对任何在 IPFS 上构建的人来说都至关重要,无论你是上传文件、构建去中心化应用,还是实现内容分发系统。本指南将拆解你需要了解的关于 IPFS CID 的所有内容、内容寻址如何工作,以及如何在你的项目中开始使用它们。

什么是 IPFS CID?
Content Identifier (CID) 是表示 IPFS 中一段内容的唯一指纹。与指向位置的传统 Web URL (例如 https://example.com/file.pdf) 不同,CID 指向内容本身,无论它存储在哪里。
可以这样理解:
- 基于位置的寻址:“去主街 123 号,要那本红书”
- 基于内容的寻址:“找 ISBN 978-0-123456-78-9 的书”(它在哪家图书馆都无所谓)
CID 的工作方式类似 —— 它们通过加密哈希识别内容,使内容具有不可变性和可验证性。如果文件中哪怕只改动一个字节,CID 也会完全改变。
为什么内容寻址很重要
传统的 Web 架构依赖基于位置的寻址。当你访问 https://example.com/image.jpg 时,你信任的是:
- 域名所有者没有更改内容
- 服务器在线且可访问
- 内容没有被篡改
使用 CID 的内容寻址:
- 不可变性:CID 保证内容没有改变
- 去中心化:可以从任何拥有该内容的 IPFS 节点检索
- 验证:你可以加密验证收到的是正确的内容
- 效率:相同内容自动去重
CID 的剖析
让我们剖析一个典型的 CID,理解它的组成部分:
bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
└─┬─┘└─────────────────┬─────────────────────────────────┘
│ │
│ └─ 内容哈希 (Base32 编码)
└─ Multibase 前缀 (指示编码方式)一个 CID 包含若干信息片段:
1. Multibase 前缀
首字符指示 CID 是如何编码的:
Q= Base58 编码 (CIDv0)b= Base32 编码 (CIDv1)f= Base16/十六进制 (CIDv1)z= Base58 (CIDv1)
2. CID 版本
- CIDv0:总是以
Qm开头,使用 SHA-256,限定为 DAG-PB 编解码器 - CIDv1:更灵活,支持多种哈希函数和编解码器
3. Multicodec
指定内容如何结构化 (DAG-PB、DAG-CBOR、原始字节等)
4. Multihash
内容的实际加密哈希,包括:
- 哈希函数标识符 (通常为 SHA-256)
- 哈希长度
- 哈希摘要
CIDv0 vs CIDv1:理解差异
IPFS 经历了两个主要 CID 版本的演进,每个版本具有不同的特性:
CIDv0:原始格式
CIDv0 的 CID 总是以 Qm 开头,形如:
QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG特性:
- 仅 Base58 编码
- 仅 SHA-256 哈希函数
- 仅 DAG-PB (Protobuf) 编解码器
- 46 个字符长
- 与所有 IPFS 实现向后兼容
何时使用 CIDv0:
- 与旧 IPFS 节点的最大兼容性
- 与期望
Qm前缀的现有系统协作 - 文件存储 (最常见用例)
CIDv1:现代标准
CIDv1 的 CID 更灵活,可能形如:
bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi # Base32
zb2rhj7crUKTQYRGCRATFaQ6YFLTde2YzdqbbhAASkL9uRDXn # Base58
f01551220d1e2c35... # Base16特性:
- 多种编码格式 (Base32、Base58、Base16)
- 支持不同哈希函数 (SHA-256、SHA-512、BLAKE2 等)
- 多种编解码器 (Raw、DAG-CBOR、DAG-JSON 等)
- 自描述格式
- 使用 Base32 时大小写不敏感
何时使用 CIDv1:
- 构建新应用
- 需要大小写不敏感的标识符
- 处理结构化数据 (JSON、CBOR)
- 使用替代哈希函数
版本间转换
你可以在版本间转换 CID,同时保持相同的内容引用:
// CIDv0
const cidv0 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
// Convert to CIDv1 Base32
const cidv1 = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi";
// Both reference the same content!内容寻址如何工作
IPFS 中的内容寻址遵循一个确定性流程,确保相同内容总是产生相同 CID:
1. 内容准备
当你向 IPFS 添加内容时,它会先被分解:
- 小文件:作为单一区块存储
- 大文件:分割成块并组织在 Merkle DAG (有向无环图) 中
- 目录:表示为链接到文件的 DAG 结构
2. 哈希过程
每段内容经历:
- 序列化:内容按其编解码器格式化
- 哈希:加密哈希函数处理序列化数据
- Multihash 创建:哈希被包装上算法和长度信息
- CID 组装:版本、编解码器和 multihash 组合
3. Merkle DAG 结构
IPFS 在 Merkle DAG 中组织内容,其中:
- 每个节点有一个 CID
- 父节点通过 CID 引用子节点
- 对任何节点的更改会沿树向上传播
- 整个结构可以加密验证
Root CID: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
├── file1.txt (QmHash1...)
├── file2.jpg (QmHash2...)
└── subdirectory/
├── file3.pdf (QmHash3...)
└── file4.mp4 (QmHash4...)实践示例:使用 CID
让我们使用 IPFS Ninja 的 API 探索如何在实践中使用 CID:
上传内容并获取 CID
// Upload a file and get its CID
const uploadFile = async (content, filename) => {
const response = await fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: btoa(content), // Base64 encode binary content
description: `Upload of ${filename}`
})
});
const result = await response.json();
console.log('CID:', result.cid);
console.log('IPFS URL:', result.uris.ipfs);
console.log('HTTP URL:', result.uris.url);
return result.cid;
};
// Example usage
uploadFile('Hello, IPFS!', 'greeting.txt');
// Returns: bafkreifjxz6zwqh27k5xnr5qfbx4w6n5vuwwwdcngguwjewzj2e3xxfgvi通过 CID 固定已有内容
如果已经有 CID,你可以固定它以确保内容保持可用:
const pinByCID = async (cid) => {
const response = await fetch('https://api.ipfs.ninja/pin', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
'Content-Type': 'application/json'
},
body: JSON.stringify({
cid: cid,
description: 'Pinned via API'
})
});
const result = await response.json();
console.log('Pinned CID:', result.cid);
return result;
};
// Pin the "Hello World" of IPFS
pinByCID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u');通过 CID 访问内容
一旦有了 CID,你可以通过多种方式访问内容:
// Direct IPFS gateway access
const ipfsUrl = `https://ipfs.ninja/ipfs/${cid}`;
// Custom gateway (if configured)
const customGatewayUrl = `https://my-app.gw.ipfs.ninja/ipfs/${cid}`;
// Fetch content programmatically
const fetchContent = async (cid) => {
const response = await fetch(`https://ipfs.ninja/ipfs/${cid}`);
const content = await response.text();
return content;
};开发者的 CID 最佳实践
1. 始终验证 CID
在应用中使用 CID 之前,验证其格式:
const isValidCID = (cid) => {
// Basic validation patterns
const cidv0Pattern = /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/;
const cidv1Pattern = /^[bf][a-z2-7]{58}$/;
return cidv0Pattern.test(cid) || cidv1Pattern.test(cid);
};2. 处理两种 CID 版本
你的应用应该同时支持 CIDv0 和 CIDv1:
const normalizeCID = (cid) => {
if (cid.startsWith('Qm')) {
// CIDv0 - can convert to CIDv1 if needed
return cid;
} else if (cid.startsWith('b') || cid.startsWith('f') || cid.startsWith('z')) {
// CIDv1
return cid;
} else {
throw new Error('Invalid CID format');
}
};3. 缓存 CID 映射
如果你频繁生成 CID,考虑缓存:
const cidCache = new Map();
const getCachedCID = (content) => {
const contentHash = btoa(content);
if (cidCache.has(contentHash)) {
return cidCache.get(contentHash);
}
// Upload and cache result
return uploadFile(content).then(cid => {
cidCache.set(contentHash, cid);
return cid;
});
};4. 使用有意义的描述
上传内容时,包含描述性元数据:
const uploadWithMetadata = async (content, metadata) => {
return fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: btoa(content),
description: metadata.name || 'Uploaded file',
metadata: {
filename: metadata.filename,
contentType: metadata.contentType,
uploadedAt: new Date().toISOString(),
version: metadata.version || '1.0'
}
})
});
};CID 的常见用例
1. 静态网站部署
将整个网站部署到 IPFS 并通过 CID 引用:
// Upload website directory structure
const deployWebsite = async (files) => {
const uploads = await Promise.all(
files.map(file => uploadFile(file.content, file.path))
);
// Root CID references entire site
const rootCID = uploads.find(u => u.path === 'index.html').cid;
console.log(`Website deployed: https://ipfs.ninja/ipfs/${rootCID}`);
return rootCID;
};要了解更多关于部署网站的内容,请查看我们关于如何上传文件到 IPFS 的指南。
2. NFT 元数据存储
使用 CID 不可变地存储 NFT 元数据:
const nftMetadata = {
name: "My Awesome NFT",
description: "A unique digital collectible",
image: "ipfs://bafkreibc5sgo2plmjkq2tzmhrn54bk3crhnqekiy7u66fqvqm37pu2e5gw",
attributes: [
{ trait_type: "Color", value: "Blue" },
{ trait_type: "Rarity", value: "Epic" }
]
};
const metadataCID = await uploadFile(
JSON.stringify(nftMetadata, null, 2),
'metadata.json'
);
// Use in smart contract
console.log(`Token URI: ipfs://${metadataCID}`);3. 内容分发
使用 CID 进行分布式内容分发:
// Upload once, access everywhere
const distributeContent = async (content) => {
const cid = await uploadFile(content, 'content.txt');
// Content available via multiple gateways
const gateways = [
`https://ipfs.ninja/ipfs/${cid}`,
`https://ipfs.io/ipfs/${cid}`,
`https://cloudflare-ipfs.com/ipfs/${cid}`
];
return { cid, gateways };
};理解 IPFS pinning 与 CID
CID 默认是临时的 —— 需要被”固定”才能保持可用。在我们关于 IPFS pinning 是什么 的综合指南中了解更多。
选择 IPFS pinning 服务时,考虑阅读我们的 IPFS Ninja vs Pinata 比较或浏览我们今天可用的最佳 IPFS pinning 服务 综述。
30 秒创建你的第一个 CID
准备好生成你的第一个 CID 了吗?这是使用 IPFS Ninja API 的快速示例:
# Using curl (replace with your actual API key)
curl -X POST https://api.ipfs.ninja/upload/new \
-H "X-Api-Key: bws_YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"content": "SGVsbG8sIElQRlMgV29ybGQh",
"description": "My first IPFS upload"
}'// Using JavaScript
const createFirstCID = async () => {
const response = await fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_YOUR_API_KEY_HERE',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: btoa('Hello, IPFS World!'), // Base64: "SGVsbG8sIElQRlMgV29ybGQh"
description: 'My first IPFS upload'
})
});
const result = await response.json();
console.log('🎉 Your first CID:', result.cid);
console.log('🌐 Access it at:', result.uris.url);
return result;
};
createFirstCID();这将返回类似:
{
"cid": "bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw",
"sizeMB": 0.000017,
"uris": {
"ipfs": "ipfs://bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw",
"url": "https://ipfs.ninja/ipfs/bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw"
}
}更多详细的 API 示例,请查看我们的 IPFS 上传 API 教程。
结论
CID 是 IPFS 内容寻址系统的基础,提供不可变、可验证和去中心化的内容识别。理解它们如何工作 —— 从 CIDv0 vs CIDv1 的技术细节到实际实现模式 —— 对构建健壮的去中心化应用至关重要。
关键要点:
- CID 唯一标识内容,而不是位置
- CIDv0 提供最大兼容性,CIDv1 提供灵活性
- 内容寻址支持验证和去重
- 正确的 CID 处理对生产应用至关重要
无论你是存储 NFT 元数据、部署去中心化网站,还是构建内容分发系统,CID 都为真正去中心化的应用提供了你所需要的可靠基础。
准备好开始 pinning 了吗? 创建免费账户 —— 50 文件、1 GB 存储、每月 2 GB 带宽。无需信用卡。