IPFS:如何将文件添加到现有文件夹?

时间:2016-10-01 07:11:26

标签: ipfs

给定一个相当大的文件夹,它已被推送到网络,并在本地删除。如何将文件添加到该文件夹​​,而不重新下载整个文件夹呢?

3 个答案:

答案 0 :(得分:11)

您只能在使用ipfs get再次下载之后使用 ipns 来执行此操作,如果它仍然固定在您的本地存储空间,则应该很快:

(1)首先以递归方式将文件夹添加(即重新添加)到ipfs:ipfs add -r /path/to/folder。最后一个stdout行的第二列包含刚刚添加的父文件夹的ipfs哈希。 (原始文件仍然相同,因此哈希也是一样的。)

(2)然后发布该哈希:ipfs name publish /ipfs/<CURRENT_PARENTFOLDER_HASH>。这将返回您的对等ID,您可以将该链接分享为/ipns/<PEER_ID>;每当文件夹内容(以及父文件夹哈希)发生更改时,重复此步骤(ipfs name publish)。然后,ipns对象将始终指向文件夹的最新版本。

(3)如果您打算共享很多内容,可以为您共享的每个文件夹创建一个新的密钥对:ipfs key gen --type=rsa --size=2048 new-share-key ...然后使用该密钥(而不是默认密钥)发布(以后再重新发布) )该文件夹:ipfs name publish --key=new-share-key /ipfs/<CURRENT_PARENTFOLDER_HASH>

另请参阅此处的文档:https://ipfs.io/docs/commands/#ipfs-name-publish

答案 1 :(得分:7)

使用文件API应该很容易。假设您已将新文件添加到ipfs并获取其哈希值,请尝试:

ipfs files cp /ipfs/QmExistingLargeFolderHash /folder-to-modify
ipfs file cp /ipfs/QmNewFileHash /folder-to-modify/new-file

这当然不会将文件添加到现有文件夹(因为文件夹和文件是不可变的),它只是创建了添加了新文件的文件夹的副本/新版本。因此,它将有一个新的哈希:

ipfs files stat /folder-to-modify

除非必要,否则文件API不会固定引用的文件或检索任何子文件夹,因此可以在网络中的任何节点上完成此操作,而不会产生大量流量。

[编辑] 过了一会儿,我了解到还有一些事情可以做:

  • 而不是

    ipfs file cp /ipfs/QmNewFileHash /folder-to-modify/new-file
    

    如果您尚未将文件添加到ipfs,则可以使用ipfs files write -te

  • 您可以启用HTTP API的写入功能,以使用PUT请求获取文件夹新版本的哈希值。见this blogpost
  • 您可以通过fuse挂载ipns并写入…/ipns/local
  • 可能最好:您可以使用ipfs object patch add-link /ipfs/QmExistingLargeFolderHash new-file /ipfs/QmNewFileHash一步完成

答案 2 :(得分:1)

我回答这个问题有点晚了,但我发现现有的 2 个答案有点不清楚。

Tl;博士;只是命令和最少的信息

如果您需要全面详细的解释,请向下滚动到以 The 2 keys to mutability 开头的部分。

如果您只需要应该运行的命令和准系统使用信息,以便您知道如何为您的用例实际调整命令,请阅读此 TL;DR;部分。

使用 IPNS / DNSLink 引用可更新的 IPFS 对象

IPNS

创建一个密钥,如果在生产中使用,请备份它,然后使用 ipfs name publish 更改您的密钥当前指向的对象。通过在命令/网址前添加 /ipns/ 而不是 /ipfs/ 来访问您的密钥。

ipfs key gen test
# backup your key if used in production
ipfs key export -o /home/somewhere/safe/test.key test
umount /ipns
ipfs name publish -k test QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs
#    Published to k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0: /ipfs/QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs

ipfs ls /ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0
# Qme85tx5Wnsjc5pZZs1JGogBNUVM2WThC18ERh6t2YFJSK 37 lorem.txt

ipfs name publish -k test QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8
#    Published to k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0: /ipfs/QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8

# Since it's not a folder this time, we use 'ipfs cat' to read 
# it to the console, since we know the file was plain text.
ipfs cat /ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0
# foo bar foo bar foo foo foo
# bar foo foo bar bar foo bar

DNSLink

在要用作 IPNS 参考的(子)域上方的 _dnslink 上设置 TXT 记录。根据您是指向 IPFS 对象还是 IPNS 地址,将该值设置为 dnslink=/ipns/<id>dnslink=/ipfs/<id>,并将 <id> 替换为您要指向的对象 ID/IPNS 地址

          Domain:     privex.io
(Subdomain) Name:     _dnslink.test
     Record Type:     TXT
           Value:     dnslink=/ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0
    TTL (expiry):     120 (seconds)

就像普通的 IPNS 一样,您现在应该可以使用 IPFS CLI 工具或 IPFS 网关通过使用 /ipns/<your_domain> 而不是 /ipfs/<object_id> 来查询它。

如果我们现在 cat /ipns/test.privex.io,我们可以看到它正常工作,指向 foo bar 文本文件(没有包装的文件夹)。

ipfs@privex ~ $ ipfs cat /ipns/test.privex.io
foo bar foo bar foo foo foo
bar foo foo bar bar foo bar

将现有的 IPFS 对象 ID 添加到另一个 IPFS 对象(包装文件夹)

使用以下命令,您可以使用各自的对象 ID 将单个 IPFS 文件或整个包装文件夹添加到现有对象中,该命令将输出一个新的对象 ID,引用一个包含原始对象的新对象文件夹数据,以及您要添加的新数据。

命令的语法是:ipfs object patch add-link [object-to-add-to] [name-of-newly-added-file-or-folder] [object-to-inject]

ipfs@privex:~$ ipfs object patch add-link QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3 hello/foo.txt QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8
QmaWoYZnSXnKqzskrBwtmZPE74qKe4AF5YfwaY83nzeCCL

可变性的两个关键

1.尽管内容发生变化,但具有保持不变的 IPFS 对象 ID

不幸的是,IPFS 对象 ID(以 Q 开头的 ID)是不可变的,这意味着在没有获得新 ID 的情况下,将来无法更改它们的内容,因为对象 ID 实际上是一个hash(通常是 SHA256 的一种形式)。

然而,IPNS 和 DNSLink 都有解决方案

IPNS 是“Interplantary Name System”,它与 IPFS 紧密集成。它允许您生成地址(公钥)和私钥,类似于比特币和许多其他加密货币的工作方式。使用您的私钥,您可以指向您的 IPNS

首先,您需要生成一个密钥(注意:您需要为您想要的每个 IPNS 地址提供一个密钥)

ipfs@privex:~$ ipfs key gen test
k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0

如果您计划将您的 IPNS 地址用于测试以外的其他目的,您应该导出私钥并将其副本保存在安全的地方。请注意,私钥是一个二进制文件,因此如果您想将其存储在需要纯文本的地方,您可以像这样将其转换为 base64:base64 test.key

ipfs key export -o /home/somewhere/safe/test.key test

接下来,我们将随机发布一个 IPFS 文件夹到 IPNS 地址,其中包含一个文件 (lorem.txt),其中包含几行 lorem ipsum 文本。如果您使用 FUSE /ipns 文件夹,您可能需要先卸载它,然后才能通过 IPNS 发布:

ipfs@privex:~$ umount /ipns

ipfs@privex:~$ ipfs name publish -k test QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs
    Published to k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0: /ipfs/QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs

ipfs@privex:~$ ipfs ls /ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0
Qme85tx5Wnsjc5pZZs1JGogBNUVM2WThC18ERh6t2YFJSK 37 lorem.txt

这只是一个示例 - 为了证明 IPNS 地址实际上可以使用不同的内容进行更新,在下一个示例中,我将直接将单个文本文件发布到 IPNS 地址(而不是打包的文件夹)。

>
# Publish the IPFS object 'QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8' 
# to our existing named key 'test'
ipfs@privex:~$ ipfs name publish -k test QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8

# Since it's not a folder this time, 'ipfs ls' won't return anything. 
# So instead, we use 'ipfs cat' to read it to the console, since we 
# know the file was plain text.
ipfs@privex:~$ ipfs cat /ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0

foo bar foo bar foo foo foo
bar foo foo bar bar foo bar

DNSLink

DNSLink 是 IPNS 的一部分,允许通过标准域系统(例如 example.com)提供人类可读的 IPNS 地址。

由于 IPNS 部分相当长,所以我将保持简短和甜蜜。如果您想了解更多关于 DNSLink 的信息,请访问 [dnslink.io](https://dnslink.io]。

首先,您要么已经有一个域名可以使用,要么您从 Namecheap 等注册商处获得了一个域名。

转到您的域记录管理面板 - 如果您使用 Cloudflare,那么它们就是您的域管理面板。为 _dnslink.yourdomain.com 添加 TXT 记录,或者如果您想使用子域 _dnslink.mysub.yourdomain.com(在大多数注册商中,您只输入您管理的域之前的部分,即 _dnslink 或 { {1}})。

在值框中,输入 _dnslink.mysub 后跟 dnslink=/ipfs/,具体取决于您要使用 IPFS 对象 ID 还是 IPNS 名称地址,然后输入您的对象 ID /IPNS 名称到最后。

例如,如果您在前面的示例中将您的域指向 IPNS 地址,您将输入:

/ipns/

或者,如果你想用几行 lorem ipsum 将它指向包含 dnslink=/ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0 的示例文件夹,那就是

lorem.txt

出于示例目的,这里总结了我如何设置 dnslink=/ipfs/QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs

test.privex.io

设置好后,IPNS地址仍然指向原始的foo bar文本数据,我用 Domain: privex.io (Subdomain) Name: _dnslink.test Record Type: TXT Value: dnslink=/ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0 TTL (expiry): 120 (seconds) (note: most people are fine with "auto" TTL, or the somewhat standard 600 TTL. If you intend to change the DNSLink value regularly, or you're experimenting and likely updating it constantly, you may want a low TTL of 60 or even 30) 读取域指向的数据:

ipfs cat

2.将现有的 IPFS 对象添加到您的对象中,而无需下载/组织要添加的对象。

首先我们创建 IPFS 对象 - 一个包含 ipfs@privex:~$ ipfs cat /ipns/test.privex.io foo bar foo bar foo foo foo bar foo foo bar bar foo bar 的包装文件夹 - 具有对象 ID hello/lorem.txt

QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3

接下来,为了创建一个不属于原始包装文件夹的示例外部对象 ID,我创建了 ipfs@privex:~$ mkdir hello ipfs@privex:~$ echo -e "lorem ipsum dolor\nlorem ipsum dolor\n" > hello/lorem.txt ipfs@privex:~$ ipfs add -p -r -w hello added Qme85tx5Wnsjc5pZZs1JGogBNUVM2WThC18ERh6t2YFJSK hello/lorem.txt added QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs hello added QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3 37 B / 37 B [=======================================================================] 100.00% ipfs@privex:~$ ipfs ls QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3 QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs - hello/ ipfs@privex:~$ ipfs ls QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3/hello Qme85tx5Wnsjc5pZZs1JGogBNUVM2WThC18ERh6t2YFJSK 37 lorem.txt ,其中包含几行随机 foo.txt 文本,并将其上传到它自己的 IPFS。它的对象 ID 是 foo bar

QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8

最后,我们使用 ipfs@privex:~$ echo -e "foo bar foo bar foo foo foo\nbar foo foo bar bar foo bar\n" > foo.txt ipfs@privex:~$ ipfs add foo.txt added QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8 foo.txt 57 B / 57 B [======================================================================] 100.00% 将我之前创建的 ipfs object patch add-link 对象(foo.txt)添加到我创建的原始包装文件夹的 QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8 文件夹内({ {1}})。

命令的语法是:hello/

QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3

它输出一个新的对象 ID ipfs object patch add-link [object-to-add-to] [name-of-newly-added-file-or-folder] [object-to-inject],它是新创建的对象的 ID,其中包含来自原始对象的 ipfs@privex:~$ ipfs object patch add-link QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3 hello/foo.txt QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8 QmaWoYZnSXnKqzskrBwtmZPE74qKe4AF5YfwaY83nzeCCL 和稍后注入的 QmaWoYZnSXnKqzskrBwtmZPE74qKe4AF5YfwaY83nzeCCL

注意:将整个包装文件夹添加到另一个包装文件夹时,此命令也有效,但要小心避免双重嵌套。例如您有 hello/lorem.txthello/foo.txt - 如果您将 Qyyyy 添加到 Qxxxx 并指定名称 Qxxxx/hello/world - 它将被添加为 Qyyyy/lorem/ipsum

如果我们现在对新对象 ID 执行 lorem,我们可以看到 Qzzzz/lorem/lorem/ipsum 子文件夹包含 ipfs lshello/ - 确认 foo.txt已成功注入副本,无需下载原始文件和 foo.txt - 然后在上传之前将它们正确组织在文件夹中。

foo.txt

总结

如第一部分所述,IPFS 对象 ID 是不可变的,因此虽然可以合并 IPFS 上的现有对象,但仍会产生新的对象 ID。

但是,通过使用 IPNS 密钥地址和/或 DNSLink,您可以拥有指向任何 IPFS 对象的可变(可编辑)引用,并且可以更新为指向新的对象 ID -需求,例如每当您更新现有对象的内容时,或者如果您决定只希望您的 IPNS 密钥/域指向完全不同的内容,您都可以这样做:)