22

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

4

3 回答 3

16

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

(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 ://docs.ipfs.io/reference/cli/#ipfs-name-publish

于 2017-05-10T20:43:36.460 回答
7

使用 files API 应该很容易。假设您已经将新文件添加到 ipfs 并获得了它的哈希值,请尝试:

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

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

ipfs files stat /folder-to-modify

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

[编辑] 过了一会儿,我了解到您可以做更多的事情:

  • 代替

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

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

  • 您可以启用 HTTP API 的写入功能以使用PUT请求来获取文件夹新版本的哈希值。请参阅此博文
  • 您可以通过 fuse 挂载 ipns 并写入…/ipns/local.
  • 可能是最好的:您可以ipfs object patch add-link /ipfs/QmExistingLargeFolderHash new-file /ipfs/QmNewFileHash一步完成
于 2017-11-15T12:46:15.280 回答
7

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

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

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

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

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

IPNS

创建一个密钥,如果在生产中使用,请备份它,然后用于ipfs name publish更改您的密钥当前指向的对象。通过前缀/ipns/命令/ URL而不是访问您的密钥/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

DNS链接

_dnslink在要用作 IPNS 参考的(子)域上方设置 TXT 记录。将值设置为dnslink=/ipns/<id>dnslink=/ipfs/<id>取决于您是指向 IPFS 对象还是 IPNS 地址,并替换<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 实际上是一个哈希(通常是 SHA256 的一种形式)。

但是,IPNS 和 DNSLink 都有解决方案

IPNS 是“跨植物名称系统”,它被强烈集成到 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

接下来,我们将向 IPNS 地址发布一个随机 IPFS 文件夹,其中包含一个文件 (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

DNS链接

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

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

首先,要么您已经有一个要使用的域,要么您从诸如Namecheap 之类的注册商处获得一个域。

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

在值框中,根据您是否要使用 IPFS 对象 ID 或 IPNS 名称地址输入,然后输入您的对象 ID/IPNS 名称到最后dnslink=/ipfs//ipns/

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

dnslink=/ipns/k51qzi5uqu5dkqxbxeulacqmz5ekmopr3nsh9zmgve1dji0dccdy86uqyhq1m0

或者,如果您想将其指向包含lorem.txt几行 lorem ipsum 的示例文件夹,它将是

dnslink=/ipfs/QmWRsWoZjiandZUXLyczXSoWi84hXNHvBQ49BiQx9hPdjs

例如,这是我如何设置的摘要test.privex.io

          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)

设置好后,IPNS地址仍然指向原始的foo bar文本数据,我曾经ipfs cat读取域指向的数据:

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

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

首先,我们创建 IPFS 对象 - 一个包含的包装文件夹hello/lorem.txt- 它具有对象 IDQmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3


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

接下来,为了创建一个不属于原始包装文件夹的示例外部对象 ID,我创建了foo.txt包含几行随机foo bar文本的示例,并将其自行上传到 IPFS。它的对象 ID 是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.txtQmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8hello/QmXCfnzXHThHwaTvSSAKeErxK48XkyVoL6ZNEhkpKmZyW3

该命令的语法是: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

它输出一个新的对象 ID QmaWoYZnSXnKqzskrBwtmZPE74qKe4AF5YfwaY83nzeCCL,它是新创建的对象的 ID,既包含hello/lorem.txt原始对象,又包含hello/foo.txt后来注入的对象。

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

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

ipfs@privex:~$ ipfs ls QmaWoYZnSXnKqzskrBwtmZPE74qKe4AF5YfwaY83nzeCCL
QmbU3BwdMarL8n6KCzVdYqMh6HEjCv6pLJQZhoVGWZ5bWW - hello/

ipfs@privex:~$ ipfs ls QmaWoYZnSXnKqzskrBwtmZPE74qKe4AF5YfwaY83nzeCCL/hello
QmaDDLFL3fM4sQkQfV82LdNqtNnyaeAmgC46Qc7FDQdkq8 57 foo.txt
Qme85tx5Wnsjc5pZZs1JGogBNUVM2WThC18ERh6t2YFJSK 37 lorem.txt

概括

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

但是,通过使用 IPNS 密钥地址和/或 DNSLink,您可以获得指向任何 IPFS 对象的可变(可编辑)引用,并且可以按需更新以指向新的对象 ID,例如,每当您更新一个现有的对象,或者如果您决定只希望您的 IPNS 密钥/域指向完全不同的东西,您可以自由地这样做:)

于 2021-03-11T16:46:17.240 回答