HeliaShare 开发实战:浏览器端 IPFS 应用的设计与实现
> 本文分享一个基于 Helia 的浏览器端 IPFS 文件分享应用的完整开发经验,从架构设计到实现细节,希望能为想要构建去中心化 Web 应用的开发者提供参考。
项目背景
HeliaShare 是一个纯前端实现的 IPFS 文件分享应用,用户可以在浏览器中直接上传文件到 IPFS 网络,通过 CID 获取文件,并主动分享本地数据块。整个应用无需后端服务器,完全运行在浏览器中。
项目地址: C:\GitHub\myblog\HeliaShare
核心功能:
- 📤 上传文件到 IPFS,自动生成多种 CID 格式
- 📥 通过 CID 获取文件,支持实时进度显示
- 🔄 自动分享本地数据块到 IPFS 网络
- 🌐 内置默认引导节点,优先获取数据
技术选型
为什么选择 Helia?
Helia 是 IPFS 协议的现代化 JavaScript/TypeScript 实现,相比已弃用的 js-ipfs,具有以下优势:
1. 模块化设计 - 按需加载功能,减少包体积 2. TypeScript/ESM - 现代化代码,更好的开发体验 3. 最新 libp2p - 支持 WebTransport 和 WebRTC 4. 浏览器原生支持 - 无需外部守护进程
技术栈
前端: 纯 HTML + ES Modules (无框架)
IPFS: Helia (通过 CDN esm.sh 加载)
传输: WebRTC-direct, WebSockets
存储: Memory Blockstore / IndexedDB
为什么不使用 React/Vue?
考虑到这是一个技术演示项目,使用原生 JavaScript 可以更清晰地展示 Helia 的核心 API 使用方式,避免框架带来的认知负担。
架构设计
整体架构
┌─────────────────────────────────────────┐
│ 浏览器 (Browser) │
│ ┌─────────────────────────────────┐ │
│ │ HeliaShare 应用 │ │
│ │ ┌─────────┐ ┌───────────┐ │ │
│ │ │ UI 层 │◄──►│ 业务逻辑 │ │ │
│ │ └─────────┘ └─────┬─────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────────▼─────┐ │ │
│ │ │ Helia IPFS 节点 │ │ │
│ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │
│ │ │ │UnixFS│ │Block│ │DHT │ │ │ │
│ │ │ └─────┘ └─────┘ └─────┘ │ │ │
│ │ └───────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
│ │ │
│ WebRTC / WebSocket │
│ │ │
└────────────────────┼────────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│引导节点 │ │IPFS网络│ │其他节点 │
└────────┘ └────────┘ └────────┘
核心模块设计
1. 节点管理模块
// 初始化 Helia 节点
async function initHelia() {
helia = await createHelia({
libp2p: {
config: {
transport: { WebSockets: {}, WebRTC: {} }
}
}
})
// 初始化存储接口
fs = unixfs(helia)
stringStore = strings(helia)
}
2. 文件操作模块
// 上传文件
async function handleFileUpload(file) {
const arrayBuffer = await file.arrayBuffer()
const cid = await fs.addBytes(new Uint8Array(arrayBuffer))
await helia.pins.add(cid) // 自动固定
return cid
}
// 获取文件
async function fetchFile(cidString) {
const cid = CID.parse(cidString)
const chunks = []
for await (const chunk of fs.cat(cid)) {
chunks.push(chunk)
}
return new Blob(chunks)
}
3. 网络管理模块
// 连接默认引导节点
async function connectToBootstrapNodes() {
for (const nodeAddr of DEFAULT_BOOTSTRAP_NODES) {
await helia.libp2p.dial(nodeAddr)
}
}
关键设计决策
1. 纯静态架构
决策: 使用纯 HTML + JavaScript,不依赖任何后端。
原因:
- IPFS 本身就是去中心化存储,不需要后端服务器
- 降低部署门槛,任何静态托管都可以运行
- 更好的隐私保护,用户数据不经过第三方服务器
<script type="module" src="app.js"></script>
import { createHelia } from 'https://esm.sh/helia@^4.0.0'
2. 默认引导节点策略
决策: 内置默认引导节点,优先从该节点获取数据。
原因:
- 提高文件获取成功率
- 减少 DHT 查找时间
- 提供更稳定的用户体验
const DEFAULT_BOOTSTRAP_NODES = [
'/ip4/164.92.116.163/udp/4001/webrtc-direct/...'
]
// 获取文件时优先尝试引导节点
if (fromBootstrap) {
// 直接连接到引导节点获取
} else {
// 通过 DHT 查找其他节点
}
3. 多 CID 格式支持
决策: 同时支持 CIDv0 (Qm开头) 和 CIDv1 (bafy开头)。
原因:
- CIDv0 兼容性更好,许多旧系统只支持这种格式
- CIDv1 是现代标准,支持更多功能
- 让用户根据需要选择合适的格式
function getCidFormats(cid) {
// CIDv0 (Base58, Qm开头)
const cidv0 = CID.createV0(cid.multihash).toString(base58btc)
// CIDv1 Base32 (bafy开头)
const cidv1Base32 = cid.toString(base32)
return { cidv0, cidv1Base32, default: cid.toString() }
}
实现细节
文件上传流程
1. 读取文件 - 使用 FileReader 或 arrayBuffer()
2. 添加到 IPFS - 使用 fs.addBytes() 生成 CID
3. 自动固定 - 使用 helia.pins.add() 防止被 GC
4. 保存记录 - 存储到 localStorage 用于历史显示
文件获取流程
1. 解析 CID - 使用 CID.parse() 验证格式
2. 查找提供者 - 优先检查默认引导节点
3. 流式下载 - 使用 for await...of 处理大文件
4. 自动下载 - 创建 Blob URL 触发浏览器下载
实时进度显示
// 模拟进度更新
const progressInterval = setInterval(() => {
const currentProgress = 30 + Math.min(50, Math.floor(receivedBytes / 1024))
updateFetchProgress(currentProgress, '正在下载...',
`从${source}接收 ${formatBytes(receivedBytes)}`)
}, 800)
// 实际下载
for await (const chunk of fs.cat(cid)) {
chunks.push(chunk)
receivedBytes += chunk.length
}
遇到的挑战与解决方案
挑战 1: WebRTC 连接问题
问题: 浏览器 WebRTC 需要在 HTTPS 环境下运行。
解决: 在文档中明确说明部署必须使用 HTTPS,并提供本地测试方案。
挑战 2: 大文件处理
问题: 浏览器内存有限,无法一次性加载大文件。
解决: 使用流式处理,分块读取和写入,避免内存溢出。
挑战 3: CID 格式兼容性
问题: 不同系统对 CID 格式的支持不一致。
解决: 同时显示多种格式,让用户自行选择。
性能优化
1. 懒加载 Helia - 页面加载后才初始化节点 2. 流式处理 - 大文件分块处理,减少内存占用 3. 本地缓存 - 使用 localStorage 缓存上传历史 4. 自动 GC - 提供垃圾回收功能,释放未固定数据
未来展望
1. 多节点支持 - 配置多个默认引导节点,提高可靠性 2. 离线支持 - 使用 Service Worker 实现离线访问 3. 加密分享 - 添加端到端加密,保护敏感文件 4. 移动端优化 - 针对移动设备的性能和流量优化
总结
HeliaShare 展示了如何在浏览器中构建一个完整的 IPFS 应用。通过合理的设计和 Helia 强大的功能,我们可以创建出既具有去中心化优势,又拥有良好用户体验的 Web 应用。
核心经验: 1. 纯前端架构完全可行,IPFS 让去中心化存储变得简单 2. 默认引导节点策略能显著提升用户体验 3. 多 CID 格式支持是兼容性的关键 4. 流式处理是处理大文件的必备技能
---
*本文是 HeliaShare 系列文章的第一篇,后续将深入探讨具体实现细节。*