使用IPFS和React的去中心化数据存储。带实例的教程

1,196 阅读6分钟

数据不断地从一个网络移动到另一个网络。在某些时候,数据需要被存储、检索、共享或删除。

在本教程中,我们将向你介绍InterPlanetary文件系统(IPFS),并演示如何通过分布式文件系统上传和存储数据。

为了用一个实际的例子来展示IPFS的运作,我们将建立一个带有React前端的DApp,并将其连接到IPFS来上传文件,并将从IPFS返回的CID存储到我们的应用程序的状态中。

下面是我们要讲的内容。

什么是IPFS?

IPFSInterPlanetary File System的缩写,是一个使用点对点网络的通信协议,通过分布式文件系统机制存储、检索和共享数据。

IPFS是一个分散的、点对点的文件共享协议。IPFS网络在网络上运行,使用内容寻址存储(CAS)来存储数据,并根据其内容而不是其位置来检索数据。IPFS使用这种方法来唯一地识别和获取有关的数据。

使用IPFS来存储存档数据,可以实现重复数据删除、集群持久性和对数据的后世的高性能。

IPFS是如何工作的?

当你把数据上传到协议上的一个现有节点时,数据会被切成更小的块,然后进行散列,并给出一个独特的内容标识符(CID),作为指纹。这使得你的数据的小块能更快更容易地在网络上快速存储。

一旦数据被上传到网络,网络内的其他节点就会更新他们的节点,以包含该数据的缓存副本。这样,他们也可以像初始节点一样提供数据。这取决于一个节点是保留并仍然提供这些数据,还是丢弃这些数据,例如,作为一种节省内存的方式。

对于每一个新上传的新数据或以前上传的数据,都会产生一个新的加密哈希值(CID),使每一个上传到网络的数据都是独一无二的,并能抵御安全漏洞或篡改。

IPFS使用一个分散的命名系统来寻找文件的名称--这就是长的CID字符串--然后使用DNSLink将CID映射到一个更容易被人阅读的DNS名称。

IPFS可供任何人使用,不仅仅是区块链开发者。这包括Web 2.0开发者、内容创建者、服务提供商、研究人员、档案管理员等等。使用IPFS的主要好处是,不管是什么用例,它都提供了一个去中心化的平台来存储和处理你的数据。

如何用IPFS和React构建前端DApp

现在我们了解了什么是IPFS以及分布式文件系统是如何工作的,让我们在React中建立一个连接到IPFS的前端实例,在那里我们将上传文件并将从IPFS返回的CID存储到我们应用程序的状态。

首先,使用npx create-react-app 命令创建一个新的React项目。在本教程中,我们将把我们的项目命名为IPFS project

npx create-react-app IPFS\ project

将目录改为新创建的文件夹,并删除代码库中任何多余的源文件。然后,用下面的JSX代码片断更新/src/App.jsx 文件。

...
const App = () => {
  return (
    <div className="App">
      <form className="form" onSubmit={handleSubmit}>
        <input type="file" name="data" onChange={retrieveFile} />
        <button type="submit" className="btn">Upload file</button>
      </form>
    </div>
  )
}
...

上面的代码提供了一个form 元素。在form 元素内,我们定义了两个额外的元素:inputbutton 。在form 元素上,我们为onSubmit 事件定义了一个函数,handleSubmit

我们还在handleSubmit 函数中定义了示例代码,以将我们从本地机器上传的文件上传到 IPFS。

最后,我们在input 元素中为onChange 事件定义了另一个函数,retrieveFile 。这个函数将帮助我们在从本地机器上传时访问文件。

Uploading Files to an Example React App Using IPFS

接下来,让我们定义上述函数,首先是retrieveFile 函数。在App 组件中,定义一个retrieveFile 函数,如下图所示。

...
const App = () => {
  const retrieveFile = (e) => {
    const data = e.target.files[0];
    const reader = new window.FileReader();
    reader.readAsArrayBuffer(data);
    reader.onloadend = () => {
      console.log("Buffer data: ", Buffer(reader.result));
    }

    e.preventDefault();  
  }

  return (
    <div className="App">
     ...
    </div>
  )
}
...

一旦文件被上传,我们将从e.target.files 数组中获取数据,然后将其传入一个FileReader 对象。

通过FileReader 对象,我们可以异步地读取我们从本地机器上传的数据内容。通过Buffer(reader.result) ,我们可以将结果转换为一个Uint8Array 数据的数组。

IPFS Project Example

现在,让我们更新App ,使用React Hook将这些数据存储在应用程序状态中 useState.

...
import { useState } from "react";

const App = () => {
  const [file, setFile] = useState(null);
  const retrieveFile = (e) => {
    ...
    reader.onloadend = () => {
      setFile(Buffer(reader.result));
    }

    e.preventDefault();  
  }
  return (
    <div className="App">
     ...
    </div>
  )
}
...

现在让我们创建第二个函数,handleSubmit 。这个函数将处理将我们从本地机器上传和处理的数据上传到IPFS的任务。

在创建这个函数之前,让我们来介绍一下访问IPFS网络的IPFS网关的可用类型。可供使用的网关有InfuraPinataFleek。这些网关中有些是免费的,有些则不是。另外,有些提供只读访问,有些则提供读写访问。

在本教程中,我们需要一个读写访问网关,因为我们要从IPFS上传和获取数据。在这个演示中,我们将使用Infura。

接下来,安装ipfs-http-client 库,它使我们能够连接到Infura。

yarn add ipfs-http-client

用下面的代码片断更新App 组件。

...
import { create } from "ipfs-http-client";

const client = create('https://ipfs.infura.io:5001/api/v0');

const App = () => {
  ...
  const [urlArr, setUrlArr] = useState([]);
  ...
  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const created = await client.add(file);
      const url = `https://ipfs.infura.io/ipfs/${created.path}`;
      setUrlArr(prev => [...prev, url]);      
    } catch (error) {
      console.log(error.message);
    }
  };

  return (
    <div className="App">
     ...
    </div>
  )
}
...

在上面的代码中,我们使用ipfs-http-client 库提供的导入的create 函数创建了一个client 实例。然后,使用client.add 函数,我们将数据上传到IPFS。

这个动作的响应会返回一个对象,其中包含上传数据的CID。使用 [https://ipfs.infura.io/ipfs/](https://ipfs.infura.io/ipfs/)URL加上存储在created 对象上的path 密钥/对值,我们可以从IPFS中检索上传的数据并将其存储在urlArr 状态中。

更新UI的JSX代码,以显示返回的URL,这些URL是我们从本地机器上传到IPFS后存储在urlArr 状态中的。

...
const App = () => {
  ...
  return (
    <div className="App">
      ...
      <div className="main">
        ...
      </div>

      <div className="display">
        {urlArr.length !== 0
          ? urlArr.map((el) => <img src={el} alt="nfts" />)
          : <h3>Upload data</h3>}
      </div>
   </div>
 )
}

接下来,从你的本地机器上传一些数据(在这个演示中我们将使用图片)到IPFS,从而在从IPFS取回时将其添加到用户界面。

Uploading Files to an Example React App Using IPFS

结论

在本教程中,我们介绍了什么是IPFS,它是如何工作的,以及如何使用可用的网关连接到P2P网络。我们建立了一个示例项目,将一个文件从本地机器上传到IPFS,然后在我们的应用程序中检索并存储返回的path ,以获取该文件。

你可以使用IPFS来建立各种东西--作为下一步,你可以考虑建立一个博客平台,一个购物车,或者一个存储代码库的远程仓库。IPFS所提供的可能性远远超出了存储数据的范围。

本教程中使用的代码可以在GitHub上找到。

The postDecentralized data storage using IPFS and React:带实例的教程首次出现在LogRocket博客上。