美文网首页
IPFS:可变文件系统

IPFS:可变文件系统

作者: 大鱼本鱼 | 来源:发表于2019-08-10 12:18 被阅读0次

    可变文件系统(MFS)允许您像使用传统的基于名称的文件系统一样,使用文件和目录。

    Lesson 1 IPFS简介

    IPFS: 星际文件系统

    IPFS,或着称为星际文件系统,是用于在去中心化网络上共享数据的对等(P2P)网络协议。 顾名思义,你可以将IPFS视为文件系统,它具有一些独特的特性,使其成为安全的,去中心化共享的理想选择。

    如果你还没有接触过,我们建议你浏览我们的去中心化数据结构教程,你可以在其中了解去中心化网络的所有信息,以及它与你熟悉的传统网络之间的区别。 在那里,你将学习有关内容寻址,加密哈希,内容标识符(CID)以及在节点间共享信息的所有内容,为了更好的理解本教程,所有这些概念都是你需要了解的。

    在IPFS中存储和共享数据

    当内容被添加到IPFS网络时,内容将会被保存在哪里?

    作为点对点数据存储系统,IPFS允许每个用户(节点)在本地托管任何他们喜欢的数据。 当你第一次向IPFS添加内容时,实际上只是将内容通过IPFS协议转换成共享格式,存储在本地设备上。 通常,我们是在自己的计算机上安装IPFS,并创建一个新的IPFS实例(也称为节点)。 这就是你的数据在本地保存的地方,并通过内容标识符(CID)引用。 存储在IPFS中的数据可以采用多种形式,但最常见的使用场景之一,是对传统文件的共享,我们将在本教程中详细了解。

    当你联网时,你可以选择与其他节点共享你的数据或文件,但如果你是唯一一个托管该资源的人,则当你的计算机离线时,其他节点将无法使用该资源。 让多个节点托管相同的文件可使资源更获得更高的可用性,并且CID(通过cryptograhpic哈希创建的唯一内容标识符)的使用也保证了系统安全。 我们将在未来的教程中详细讨论共享,但是现在我们将专注于如何在你自己的IPFS实例中处理文件。

    可变文件系统(Mutable File System)

    因为IPFS中的文件是内容寻址并且无法篡改的,所以你无法编辑文件; 因此,每次更改都会创建一个新文件。 可变文件系统(MFS)是一个内置于IPFS中的工具,可以让你像在基于名称的文件系统中一样处理文件 - 你可以添加,删除,移动和编辑MFS文件,并自动帮你完成更新链接和创建哈希的所有工作。 它是一种抽象概念,可以让你像处理可变数据一样,处理不可变数据。

    可以通过调用IPFS CLI(命令行界面)和API中的files命令访问MFS。 在本教程中,我们将探索Files API

    如果你之前使用过命令行中的文件和目录,那么许多MFS方法看起来都因该非常熟悉!

    让我们开始探索如何使用IPFS中的文件!

    Lesson 2 查看目录状态

    使用ProtoSchool中的文件

    在我们的ProtoSchool教程中,当你每次点击课程中的“提交”按钮时,我们都会在浏览器中为您创建一个新的IPFS节点。 每当你在我们的课程中看到ipfs.someMethod()时,ipfs就是一个引用你的IPFS实例的变量,也称为节点。 你执行的操作仅影响你自己的IPFS节点,而不影响属于你的peers上的节点。

    我们正在后台创建你的IPFS节点,以便你可以专注于我们的课程,但最终你需要学会安装IPFS并在终端中运行程序来启动你自己的本地节点。 当你准备好进行实验时,可以在我们的文档中找到有关安装IPFS初始化节点的说明文档。

    如前所述,与可变文件系统相关的方法是Files API的一部分,因此它们将采用ipfs.files.someMethod()的格式。 让我们看一下即使在将任何文件添加到IPFS节点之前也可以开始使用的简单方法。

    使用ipfs.files.stat探索IPFS节点

    使用IPFS节点时,通常需要检查文件或目录的状态。 您可以使用ipfs.files.stat执行此操作,传入你要查看的路径。

    例如,要查看位于根目录(/)中的名为stuff的目录的状态,我们可以像这样调用方法:

    await ipfs.files.stat('/stuff')

    此方法返回一个包含有关我们的文件或目录的基本数据的对象:

    • hash(带有加密哈希的字符串)
    • size(文件或目录大小,以字节为单位的整数)
    • cumulativeSize(以字节为单位构成DAGNodes文件的整数大小)
    • type(可以是目录或文件的字符串)
    • blocks(如果type是目录,这是目录中的文件数;如果type是文件,则是组成文件的块数)
    • withLocality(一个布尔值,表示是否存在位置信息)
    • local(一个布尔值,表示查询的dag是否完全存在于本地)
    • sizeLocal(一个整数,表示本地存在的数据的累计大小)

    注意!目录的size始终为0,无论它包含多少条目,因为目录实际上只是一组指向其他文件和目录的链接。相反,目录的cumulativeSize会随着目录内容的变化而变化。它不仅代表该目录中所有条目的文件大小,还代表描述这些条目的元数据:类型,块大小等。

    需要注意的是,即使你的IPFS节点还没有任何内容,也可以用stat对它进行查看。即使是空节点也有CID(哈希)。

    小练习

    Lesson 3 使用ProtoSchool中的文件

    出于安全考虑,Web浏览器不允许我们直接更改计算机文件系统中的文件。 因此,你需要将一个或多个文件上传到本教程中使用的浏览器。

    在每个练习中,你会发现可以通过拖放或从文件资源管理器中选择文件来上传文件。 如果仔细查看代码编辑器中的run函数,你会发现它现在需要一个参数files。 当您从计算机上传文件时,我们必须确保它们作为文件数组传递给函数。 只要你不刷新浏览器,这些文件将在本教程的下一课中保持可访问状态,但你也可以选择上传不同的文件以供每节课使用。

    练习准备工作,请从你的计算机上传一个或多个文件,并查看浏览器收到的文件数组。

    小练习

    Lesson 4 将文件添加到MFS

    现在我们可以在浏览器中访问文件,让我们看看如何将它们添加到IPFS中。
    要将文件添加到IPFS,我们可以使用MFS files.write方法,如下所示:

    await ipfs.files.write(path, content, [options])

    MFS的 files.write方法可以接受BufferReadableStreamPullStreamBlob(仅在浏览器中)或string path(仅在Node.js中)形式的文件。浏览器中的文件对象是一种Blob格式,我们继续!

    即使浏览器中的文件对象碰巧知道自己的文件名,Blob通常也不知道,因此IPFS无法直接确定真实的文件名。我们必须提供所需的文件名作为path的一部分。

    path是你要在IPFS实例中创建的新路径,包括所需的文件名。 (请注意,它是我们描述的目标路径,而不是文件已经保存在你的计算机上的路径。)

    MFS files.write方法与你在自己的计算机上使用的方法类似,实际上是为编辑现有文件的内容而构建的。不过,如果在给定的路径不存在这个文件,我们也可以通过一个布尔类型的选项{create : true}来创建一个全新的文件。

    因此,如果我们的浏览器中有一个文件对象,可通过变量catPic访问,并且我们想将它添加到IPFS上的根目录并将其命名为cat.jpg,我们可以这样做:

    await ipfs.files.write('/cat.jpg', catPic, { create : true })

    如果有必要,我们可以使用拼接字符串(将字符串连接在一起)的方式来创建相同的路径。 如果你的文件名是文件对象的属性,这种方法在浏览器中使用就很方便。

    await ipfs.files.write('/' + catPic.name, catPic, { create : true })

    请注意,files.write方法不提供返回值。
    稍后我们将介绍如何将文件添加到根目录以外的目录。

    小练习

    Lesson 5 查看目录的内容

    当我们使用files.write向MFS添加文件时,该方法没有返回任何值,但我们仍然可以检查以确保一切按预期工作。
    在Mutable File System中,我们可以使用files.ls方法检查目录。 如果你曾使用命令行列出计算机上目录的内容,那么对这种方法应该会非常熟悉。
    file.ls方法如下所示:

    await ipfs.files.ls([path], [options])

    该方法默认列出根目录(/)的内容,或者你可以选择指定要检查的特定path(目录),例如/ catPics,
    file.ls生成一个对象数组,你正在查看的目录中的每个文件或目录,具有以下属性:

    • name(默认值):文件名
    • type({long : true} 可选项):对象的类型(0 -文件 或 1 - 目录)
    • size({long : true} 可选项):文件的大小(以字节为单位)
    • hash({long : true} 可选项):表示IPFS文件的加密哈希或内容标识符(CID)

    注意!要返回所有这些属性的值,必须使用选项{long : true}。 否则,除名称字段外的所有属性都将返回为0(对于size和type)或""(对于hash)

    如果我们想查看 /catPics 目录下所有内容的详细信息,我们可以这样做:

    await ipfs.files.ls('/catPics', { long : true })

    你可以在files.ls API文档中了解有关其他选项的更多信息。

    小练习

    Lesson 6 了解CID如何随着数据的变化而变化

    正如你在去中心化数据结构教程中所了解到的,CID(内容标识符)与它们通过加密哈希表示的内容一一对应。 具有相同内容的两个文件具有相同的CID(哈希),并且就算只有一点点差异的两个文件,都具有不同的CID。 目录也是如此。 每次更新文件或目录的内容时,其CID都会更改。

    当你的根目录为空并且使用ipfs.files.stat检查其状态时,你会看到以下结果:

    {
      "hash": "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn",
      "size": 0,
      "cumulativeSize": 4,
      "blocks": 0,
      "type": "directory",
      "withLocality": false
    }
    

    你现在添加了一个或多个文件会是什么样子? 哪些字段现在应该更改?

    小练习

    Lesson 7 创建一个目录

    我们已经学会了如何将文件添加到根目录,但是我们如何创建一个新目录呢? 同样的,这与你在自己计算机上使用命令行的过程非常相似。

    MFS的files.mkdir方法在指定路径创建新目录。 例如,要将一个叫images目录添加到根目录(/),我们可以这样做:

    await ipfs.files.mkdir('/images')

    可选项parents(默认为false)指定了在给定的路径中,如果有父目录不存在的情况,是否要创建该父目录。 这在上面的例子中不需要,因为新的images目录是现有目录(/)的直接子目录。 但是,如果我们想要创建一个还不存在的新目录,我们需要将parent的值显式设置为true,如下所示:

    await ipfs.files.mkdir('/my/beautiful/images', { parents : true })

    注意!虽然创建不存在路径的方法是类似的,但请注意我们使用files.mkdir的{parents : true}选项,而不是files.write提供的{create : true}选项。

    小练习

    Lesson 8 移动文件或目录

    MFS允许你使用files.mv方法在目录之间移动文件,就像在本地计算机上一样。

    该方法如下所示:

    await ipfs.files.mv(...from, to, [options])

    from是你要移动的内容的源路径(或路径)。 to是目标路径。

    如果目标路径引用了尚不存在的上级路径,则需要使用{parents : true}选项,就像使用files.mkdir一样。

    你可以使用files.mv执行许多不同的操作:

    // move a single file into a directory
    await ipfs.files.mv('/source-file.txt', '/destination-directory')
    
    // move multiple files into a directory (note the two acceptable formats)
    await ipfs.files.mv('/source-file-1.txt', '/source-file-2.txt', '/destination-directory')
    await ipfs.files.mv(['/source-file-1.txt', '/source-file-2.txt'], '/destination-directory')
    
    // move a directory into another directory
    await ipfs.files.mv('/source-directory', '/destination-directory')
    
    // overwrite the contents of a destination file with the contents of a source file
    await ipfs.files.mv('/source-file.txt', '/destination-file.txt')
    

    小练习

    Lesson 9 复制文件或目录

    与files.mv不同,files.mv在将项目移动到其目标路径后删除其源路径中的项目,files.cp方法允许你将文件或目录复制到新位置,同时保留源位置的项目。

    该方法如下所示:

    await ipfs.files.mv(...from, to, [options])

    from是你要移动的内容的源路径(或路径)。 to是目标路径。
    如果目标路径引用了尚不存在的父目录,则需要使用{parents : true}选项,就像使用files.mkdir一样。
    你可以使用files.mv执行许多不同的操作:

    // move a single file into a directory
    await ipfs.files.mv('/source-file.txt', '/destination-directory')
    
    // move multiple files into a directory (note the two acceptable formats)
    await ipfs.files.mv('/source-file-1.txt', '/source-file-2.txt', '/destination-directory')
    await ipfs.files.mv(['/source-file-1.txt', '/source-file-2.txt'], '/destination-directory')
    
    // move a directory into another directory
    await ipfs.files.mv('/source-directory', '/destination-directory')
    
    // overwrite the contents of a destination file with the contents of a source file
    await ipfs.files.mv('/source-file.txt', '/destination-file.txt')
    

    小练习

    Lesson 10 浏览文件的内容

    MFS有一个files.read方法,允许你在缓存中显示文件的内容。 这使我们可以轻松读取.txt文件的内容。

    该方法采用以下格式:

    await ipfs.files.read(path, [options])

    path是要读取的文件的路径,它必须指向文件而不是目录。
    files.read方法返回一个Buffer,可以使用 toString('utf8') 方法将其转换为字符串。 例如:

    let bufferedContents = await ipfs.files.read('/directory/some-file.txt')  // a buffer
    let contents = bufferedContents.toString('utf8') // a string
    

    或者

    let contents = (await ipfs.files.read('/directory/some-file.txt')).toString('utf8') // a string
    // notice the parentheses around the entire await statement
    

    当你准备在真机上尝试此操作时,你需要注意files.read方法可能会因为读取的文件太大,从而导致大量内存被占用。 你可能希望通过files.readReadableStreamfiles.readPullStream方法来进行进行文件内容的浏览。

    小练习

    Lession 11 删除文件或目录

    MFS允许您使用files.rm方法删除文件或目录:

    await ipfs.files.rm(...paths, [options])

    paths是要删除的一个或多个路径。

    默认情况下,如果你尝试删除非空目录,则将导致操作失败。 要删除目录及其中包含的所有内容,你需要使用{recursive : true}选项。

    // remove a file
    await ipfs.files.rm('/my/beautiful/file.txt')
    
    // remove multiple files (note the two acceptable formats with or without [ ])
    await ipfs.files.rm('/my/beautiful/file.txt', '/my/other/file.txt')
    await ipfs.files.rm(['/my/beautiful/file.txt', '/my/other/file.txt'])
    
    // remove a directory and its contents
    await ipfs.files.rm('/my/beautiful/directory', { recursive: true })
    
    // remove a directory only if it is empty
    await ipfs.files.rm('/my/beautiful/directory')
    

    小练习

    资料

    探索更多学习资料

    协议学院 上海分院 翻译
    原文链接

    相关文章

      网友评论

          本文标题:IPFS:可变文件系统

          本文链接:https://www.haomeiwen.com/subject/hpgurctx.html