moon

moon

Build for builders on blockchain
github
twitter

IPFS 簡介

官網

簡介#

星際文件系統InterPlanetary File System,縮寫為IPFS)是一個旨在實現文件的分佈式存儲、共享和持久化的網絡傳輸協議。它是一種內容可尋址的對等超媒體分發協議。在 IPFS 網絡中的節點構成一個分佈式文件系統

主要有以下幾個特點:

  • 支持彈性網絡:在傳統的互聯網中,文件是存儲在中心化伺服器上的,假如你的文件伺服器宕機了。就會導致文件不可訪問。但在IPFS中,你還可以從其他節點獲取文件。
  • 內容審核更困難:因為IPFS上的文件可以來自很多地方,所以任何人都更難封鎖。
  • 更快的文件獲取速度:由於你可以從附近的節點上獲取文件。而不是其他更遠的地方,所以大大提升了訪問速度。(類似於 CDN)

今天的萬維網是以所有權和訪問權為結構的,這意味著你要想從擁有者那裡獲得文件,必須要先獲得訪問權。但IPFS是基於佔有和參與的理念的,即人們擁有著彼此的文件並參與提供文件。

IPFS只有在人們積極參與的情況下才能更好的運轉。如果你用你的電腦使用IPFS共享文件,但後來你關閉了,其他人就不能再從你那裡獲得文件。但是,如果文件的副本存儲在其他運行著IPFS的計算機上,則這些文件就可以做出共享。

工作原理#

IPFS 遵循了三個基本原則

  • 透過內容尋址來進行唯一的標識

    一般情況下文件的路徑是基於位置,無論是你本地的文件 /Users/..../code.js 還是網絡上可訪問的文件 http://www.google.com/index.html

    IPFS 的文件路徑不是基於地址的,而是基於文件內容。IPFS會基於文件內容生成一個加密的哈希值,這個值用來作為路徑的一部分,如下面地址中 ipfs/ 後面的內容

    /ipfs/QmcuLr8xuHm6ViSYuppjDxCXE8vDuUBKmdAwcrTJRRnEUY
    

    IPFS 使用內容尋址,即透過內容而不是透過它的位置來定位文件。每個使用 IPFS 協議的文件都有一個內容標識符,即 CID,也就是它的哈希值。這個哈希值對於文件來說是獨一無二的。

  • 透過有向無環圖 (DAG) 進行內容鏈接

    IPFS和許多其他分佈式系統一樣使用了一種稱為有向無環圖 (DAG) 的數據結構。具體來說,是使用了默克爾有向無環圖 (Merkle DAG)。

    為了建立一個Merkle DAG表示你的文件,IPFS通常首先將文件分塊。(分塊意味著文件的不同部分可以有不同的來源,並被快速驗證)。分塊的內容會經過哈希運算得到一個哈希值作為CID,並作為 Merkle DAG 的節點。 這些節點再次經過哈希運算也就得到了該文件的CID

    同樣,如果文件處於文件夾內,則也會根據文件夾內的文件內容經過哈希運算得到文件夾的CID

    如果你有兩個類似的文件,文件分塊後生成的CID如果有相同的,則可以引用相同的數據子集,可以很好地達到去重的效果。

    例如,更新文件時,更新的文件和未更新文件的第一個塊的CID相同,則可以引用相同的塊。而不是重新創建。

    因此,概括地說,IPFS讓你為內容賦予 CID,並將這些內容連接在Merkle DAG中。

  • 透過分佈式哈希表 (DHT) 發現內容

    DHT的最主要思想是全網維護一個巨大的文件索引哈希表,這個哈希表的條目形如<Key,Value>。其中,Key通常是文件的某個哈希算法下的哈希值 (也可以是文件名或者文件內容描述),而Value則是存儲文件的 IP 地址。查詢時,僅需要提供Key,就能從表中查詢到存儲節點的地址。

    由於這個哈希表很大,因此它會被分割成小塊,按照一定的算法和規則分布到全網各個節點上。每個節點僅需要維護一小塊哈希表,但每塊哈希表不止由一個節點維護(這樣即使節點意外掛掉也有其他的節點使DHT可用)。

    當節點接受到查詢請求後,如果可以在自己的桶(每一個節點維護的DHT子集被稱為” 桶 “)中找到則回覆,否則聯繫最近節點回覆。這個過程一直到找到目標節點為止。

這三個原則相互依存,實現 IPFS 的生態系統。

使用#

命令行使用#

命令行安裝 js-ipfs

$ npm install -g ipfs

也可以安裝客戶端 https://ipfs.tech/#install

初始化ipfs倉庫

$ jsipfs init
initializing ipfs node at .jsipfs

啟動本地 ipfs 網絡實例

$ jsipfs daemon
Initializing IPFS daemon...
HTTP API listening on /ip4/127.0.0.1/tcp/5002/http
gRPC listening on /ip4/127.0.0.1/tcp/5003/ws
Gateway (read only) listening on /ip4/127.0.0.1/tcp/9090/http
Web UI available at http://127.0.0.1:5002/webui
Daemon is ready

添加文件

$ jsipfs add util.ts
added QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH util.ts

訪問文件內容

$ jsipfs cat QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH

API 使用#

首先需要一個可以公網訪問的伺服器作為 ipfs 節點。可以選擇自己的公網伺服器或者 infura 服務。這裡就以 infura 為例,而且其還有著 5G 的免費空間可以使用。在 infura 上創建 ipfs 項目後會有一個 projectIdprojectSecret

安裝#

項目中安裝 ipfs-http-client

$ yarn add ipfs-http-client

初始化#

import { create, urlSource, CID } from 'ipfs-http-client'
import fs from 'node:fs'

const projectId = 'xxxxxx'
const projectSecret = 'xxxxxx'

const auth = 'Basic ' + Buffer.from(projectId + ':' + projectSecret).toString('base64')

const ipfs = create({
  host: 'ipfs.infura.io',
  port: 5001,
  protocol: 'https',
  headers: {
    authorization: auth
  }
})

上傳資源#

const upload = async () => {
  // 上傳本地文件 或 網絡資源 或 文本
  
  // 1. 本地資源
  const file = fs.readFileSync('./test.sol', 'utf-8')
  // 2. 網絡資源
  //const file = urlSource('https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png')
  // 3. 文本
  // const file = 'hello world'

  const result = await ipfs.add(file)

  console.log(result)
}
upload()

上傳成功後會返回如下格式的內容

{
  path: 'QmNvHxnJQ6Ho9LWw1FwCn3nqcJXSeM76cmmd6JvoLEzW8Q',
  cid: CID(QmNvHxnJQ6Ho9LWw1FwCn3nqcJXSeM76cmmd6JvoLEzW8Q),
  size: 593
}

通過瀏覽器的地址 https://ipfs.infura.io/ipfs/${path},即可訪問內容

讀取資源#

const cat = async () => {
  const decoder = new TextDecoder();
  let content = '';
  for await (const chunk of ipfs.cat('QmNvHxnJQ6Ho9LWw1FwCn3nqcJXSeM76cmmd6JvoLEzW8Q')) {
    content += decoder.decode(chunk);
  }
  console.log(content)
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。