IPFSのMFS(Mutable file system)を扱うためのFIles-APIに入門するので、まとめておく
目次
- await ipfs.files.stat(path)
- await ipfs.files.write(path, content, [options])
- await ipfs.files.ls([path], [option])
- await ipfs.files.mkdir(path, [option])
- await ipfs.files.mv(from, to, [options])
- await ipfs.files.cp(…from, to, [options])
- await ipfs.files.read(path, [options])
- await ipfs.fies.rm(…path, [options])
- まとめ
await ipfs.files.stat(path)
あるディレクトリまたはファイルの状態を取得してこれる。
{
"cid": {
"codec": "dag-pb",
"version": 0,
"hash": {
"0": 18,
"1": 32,
"2": 89,
"3": 148,
"4": 132,
"5": 57,
"6": 6,
"7": 95,
"8": 41,
"9": 97,
"10": 158,
"11": 244,
"12": 18,
"13": 128,
"14": 203,
"15": 185,
"16": 50,
"17": 190,
"18": 82,
"19": 197,
"20": 109,
"21": 153,
"22": 197,
"23": 150,
"24": 107,
"25": 101,
"26": 224,
"27": 17,
"28": 18,
"29": 57,
"30": 240,
"31": 152,
"32": 187,
"33": 239
}
},
"size": 0,
"cumulativeSize": 4,
"blocks": 0,
"withLocality": false,
"type": "directory",
"mode": 493
}
こんな感じで帰ってくるが、cidの部分が見にくすぎでどうすればいいか→
cidプロパティにはtoString()メソッドがあるらしく、それをすると、こうなる。視認性が天と地の差。
{
"cid": "CID('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn')",
"size": 0,
"cumulativeSize": 4,
"blocks": 0,
"withLocality": false,
"type": "directory",
"mode": 493
}
await ipfs.files.write(path, content, [options])
writeメソッドのcontentにはさまざまなデータが対応している。
Buffer, ReadableStream, PullStream, Blob (ブラウザのみ), パス文字列 (Node.jsのみ)
メソッドの第一引数に「path」とあるが、これはファイル名を指定する。
ブラウザから、自身のコンピューターのファイルをアップロードした場合だいたいそのファイルの名前がついているので意識しなくて良いが、単なるデータオブジェクトを送信したい場合もある。そう言ったときに、ファイル名を指定してあげる必要がある。
optionsには、オプションを指定することができる。
{create: true}
createというbooleanのオプションでは、指定されたpathにファイルが存在しない時だけファイルを追加するという制約を示す。
await ipfs.files.ls([path], [option])
lsコマンドのようにディレクトリの中身を確認することができるAPIです。
返り値は配列(厳密には違います。。下部分参照)で、それぞれの要素は、以下のキーをもったオブジェクトです!
name
:ファイルの名前type
:オブジェクトのタイプ(0
ならファイル、1
ならディレクトリ)size
:ファイルのサイズ(バイト単位)cid
:IPFSでファイルを識別するコンテンツ識別子(CID)mode
:UnixFSのモード()mtime
:secs
とnsecs
プロパティを持つオブジェクト
注意事項
ipfs.files.ls()のAPIは、配列を一気に返してくるわけではありません。ipfsの特性上、Async.Iterable値を返します。
jsをそれなりに使いこなせる開発者の皆様もAsync.Iterableを実務で使ったことは少なそう。。
配列のオブジェクトを一つ一つ非同期的に返してくるということですね!
jsの中でもかなりマイナーな構文を使うことで、配列として取得することができます!
参考url (https://proto.school/mutable-file-system/05)
const result = []
for await (const resultPart of ipfs.files.ls('/catPics')) {
result.push(resultPart)
}
return result
for await of文です。これは非同期的に返ってくる.files.lsの返り値をjs内で扱いやすい配列に変換するコードです!
この関数をwrapした it-all といったパッケージも存在するようです。
await ipfs.files.mkdir(path, [option])
このAPIは、第一引数に指定したpathに新しくディレクトリを作成します。
optionの一つに、parentsがあります。booleanのオプションで、デフォルトはfalseです。
これは、まだ存在していないディレクトリの下に新しくディレクトリを作るときにつけるオプションです。
/parents/child
parentsディレクトリが存在していないときに、childディレクトリを作成する場合は、{parents: true}を指定してあげる必要があります。
Unixコマンドのmkdirの-pオプションと同じですね。
await ipfs.files.mv(from, to, [options])
fromには、動かしたいファイルまたはディレクトリのpathです。
toには、動かす先のパスです。
optionは、オプションが入ります。
optionには、booleanのparentsオプションがあります。
これは、mkdirの段落で説明したparentsオプションと同じ意味ですので、説明は割愛します。。
fromには、複数のファイルを指定することができますので、jsのスプレッド構文が使えます。
await ipfs.files.cp(…from, to, [options])
mvメソッドと同じ引数です。mvとcpの違いは、fromに指定するファイルを削除するかしないかと言うことです。
mvは削除し、cpはそのままにしておきます。
しかし、第一引数のfromに入れる値として、以下の二つの場合があります!
- すでに存在しているMFS(mutable file system)のパス
- 自分自身のnodeにある必要がある?(←ちょっとわからない。。)
- IPFSパス
- 自分もしくは他のネットワーク参加者(peer)にホスティング(管理)されているファイルもしくはディレクトリのパスです
cp APIは、引数の取り方で、いくつかの異なる挙動をとりますので紹介します。参考
一つのファイルをディレクトリ内にコピー
await ipfs.files.cp('/source-file.txt', '/destination-directory')
await ipfs.files.cp('/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks', '/destination-directory')
複数のファイルを一つのディレクトリにコピー
// []があってもなくても同じ動きをします。
await ipfs.files.cp('/source-file-1.txt', '/source-file-2.txt', '/destination-directory')
await ipfs.files.cp(['/source-file-1.txt', '/source-file-2.txt'], '/destination-directory')
await ipfs.files.cp('/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks',
'/ipfs/QmWGeRAEgtsHW3jk7U4qW2CyVy7eA2mFRVbk1nb24jFyre', '/destination-directory')
await ipfs.files.cp(['/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks',
'/ipfs/QmWGeRAEgtsHW3jk7U4qW2CyVy7eA2mFRVbk1nb24jFyre'], '/destination-directory')
一つのディレクトリを他のディレクトリにコピー
await ipfs.files.cp('/source-directory', '/destination-directory')
await ipfs.files.cp('/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks', '/destination-directory')
await ipfs.files.read(path, [options])
files.readメソッドは、バッファ内にあるファイルの中身を表示することができます。
これは特に、.txt拡張子のファイルを読み取りやすくします。
今回は、第一引数のパスは、ディレクトリではなくファイルである必要があります!
注意点!
以下のコードをご覧ください。
// the toBuffer variable is globally available (just like ipfs)
let bufferedContents = await toBuffer(ipfs.files.read('/directory/some-file.txt')) // a buffer
let contents = bufferedContents.toString() // a string
実際の開発でこのコード構造を使用する場合は、注意する必要があるそうです。
なぜなら、非常に大きなメモリ使用量になる可能性があるからです。
特に、サイズの大きなファイルを使用する時は注意してほしいとのこと。
大きなファイルを読み込むときは、it-to-bufferのパッケージを使用する代わりに、それぞれのデータの塊ごとに繰り返し処理をする方がいいです。
理由は、IPFSがAsync Iterable型を返すようになっているからです。パフォーマンスの問題を解消するために、ipfsではデフォルトでこのようになっています。
await ipfs.fies.rm(…path, [options])
引数には、削除したいファイル、ディレクトリのパスを複数指定できます。
複数のファイルのパスを指定する時は、cpの時と同様に、配列のように指定することもできます。
recursive オプション
ディレクトリを削除するときに、
await ipfs.files.rm('/my/beautiful/directory')
こうすると、指定したディレクトリの内部が空の時以外は、エラーになります。ディレクトリの内部ごと一気に削除したい場合は、recursiveオプションをtrueにする必要があります。
await ipfs.files.rm('/my/beautiful/directory', { recursive: true })
まとめ
一通り、チュートリアルにあるものを日本語にまとめてみました!これを使って開発するのが待ちきれません。。😆