Fleek StorageにASW SDKからアクセスする

2022.08.03

Fleek StorageはAWS S3と互換性があるため、S3とIPFSの間でファイルを非常に簡単に統合および移動することが可能となっています。

以前の記事でAWS S3 コマンドラインインターフェイスとの統合を試しましたが、今回はAWS SDKを使ってFleekにアクセスしてファイルを操作して見たいと思います。

やってみる

APIキーが必要となるので、FleekのWebコンソールから作成しておきましょう。

APIキーの取得

AWS SDKのインストール

S3のSDKとの統合を行うために、まず 依存関係であるAWS SDKをインストールします。

$ cd [[プロジェクトフォルダ]]
$ npm init
$ npm install --save aws-sdk

S3クライアントの生成

S3 SDKを使ってFleek Storageにアクセスするため、S3クライアントのインスタンスをプログラムから生成します。

$ vi app.js

でファイルを作成し、以下のコードを記述します。

const AWS = require('aws-sdk');

const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  accessKeyId: '[[apiKey]]',
  secretAccessKey: '[[apiSecret]]',
  endpoint: '[[endpoint]]',
  region: 'us-east-1',
  s3ForcePathStyle: true
});

[[apiKey]][[apiSecret]]は作成したAPIキーとシークレットを使用します。

[[endpoint]]ですが、ここにFleekのURLを指定することによってS3ではなく、Fleek Storageにアクセスできるようになります。

  • 共有ゲートウェイのURL https://storageapi2.fleek.co
  • バケット固有のURL https://[bucketName].s3.fleek.co/

を使えます。

注意

上記のようにバケット名が0c82ebdb-00c4-461c-acb2-d582d7ea4f18-bucketなら バケット固有のURLは https://0c82ebdb-00c4-461c-acb2-d582d7ea4f18-bucket.s3.fleek.co/ となります。

が、実際に試してみるとエラーになりました。

Error [XMLParserError]: Unexpected close tag

まだ開発中なのかもしれません。

今回は共有ゲートウェイのURLをエンドポイントに指定します。 これで、s3.メソッド名 を使ってFleekにアクセスできるようになります。

s3.listBuckets, s3,putObject など。

S3のメソッドを使ってFleek Storageを操作してみる

バケット取得 (listBuckets)

アカウントに関連づけられているFleekのバケットをlistBuckets()で取得できます。

s3.listBuckets(function (err, data) {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});

を実行すると、。

{
  Buckets: [
    {
      Name: '0c82ebdb-00c4-461c-acb2-d582d7ea4f18-bucket',
      CreationDate: 2022-07-28T05:56:58.706Z
    }
  ],
  Owner: {
    DisplayName: 'minio',
    ID: '02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4'
  }
}

のようにS3ではなくFleek Storageのバケットの一覧が返ってきます。

バケット内のファイルの一覧 (listObjectsV2)

バケット内のファイルは、S3 クライアント インスタンスとバケット名を指定して一覧表示できます

このバケットのファイル一覧をS3 SDKで取得してみます。

const params = {
  Bucket: "[[Fleek Storageのバケット名]]",
  MaxKeys: 20
};

s3.listObjectsV2(params, function (err, data) {
  if (err) {
    console.log("Error when listing objects", err);
  } else {
    console.log("Success when listing objects", data);
  }
});

を実行すると、

{
  IsTruncated: false,
  Contents: [
    {
      Key: 'assets/',
      LastModified: 2022-07-29T02:19:10.045Z,
      ETag: '"QmWysDnBBjqZFbACMbMHM5FNHQ6pXgbb8WhKBykVsf3jcd"',
      ChecksumAlgorithm: [],
      Size: 0,
      StorageClass: 'STANDARD',
      Owner: [Object]
    },
    {
      Key: 'test.txt',
      LastModified: 2022-07-29T04:20:26.595Z,
      ETag: '"bafybeick2oidocd2ruow3tz73sqh2uq2k4rbxemopacr3tm5hw77mphmqq"',
      ChecksumAlgorithm: [],
      Size: 19,
      StorageClass: 'STANDARD',
      Owner: [Object]
    },
~~~ <<省略>> ~~~
  ],
  Name: '0c82ebdb-00c4-461c-acb2-d582d7ea4f18-bucket',
  Prefix: '',
  Delimiter: '',
  MaxKeys: 20,
  CommonPrefixes: [],
  KeyCount: 4
}

きっちりとFleekに保存されたデータが返ってきました。

Etagの値がCurrent IPFS Hashの値になっていますね。

ファイルのアップロード (putObject)

putObjectを介してコマンドを使用して、バケットにファイルをアップロードできます

$ cat hoge.txt
hogehoge

このテキストファイルをアップロードしてみます。

const fs = require('fs')
const fileBody = fs.readFileSync("./hoge.txt");

const params = {
  Body: fileBody, // Binary String
  Bucket: [[bucketName]],
  Key: "hoge.txt"
};

s3.putObject(params, function(err, data) {
   if (err) console.log(err, err.stack);
   else     console.log(data);
});

パラメーターのBodyには、アップロード元ファイルのバイナリを与えます。

実行すると、

{
  ETag: '"bafybeiasacmdru6kdlvjvlr3rp3snnsqx53aoo2nyal726xqueh454z4ea"'
}

とEtagが返ってきます。

Webコンソール上でも追加できていることを確認できました。

フォルダごとアップロードする場合は、

const fileBody2 = fs.readFileSync("images/cd1f9b3.svg");
const params2 = {
  Body: fileBody2,
  Bucket: bucket,
  Key: "images/cd1f9b3.svg"
}

といった感じでKeyにフォルダも含めると、

状態を維持してアップロードされます。

ファイルのダウンロード

getObjectを介してコマンドを使用して、バケットにアップロードされたファイルをダウンロードできます

先ほどアップロードしたhoge.txtをダウンロードするためには、以下のコードを実行します。

const params = {
  Bucket: [[bucketName]],
  Key: "hoge.txt"
};

s3.getObject(params, function(err, data) {
   if (err) console.log(err, err.stack);
   else     console.log(data);
});

パラメーターにBucket名とKeyを指定し、実行すると

{
  AcceptRanges: 'bytes',
  LastModified: 2022-08-02T03:20:03.000Z,
  ContentLength: 9,
  ETag: '"bafybeiasacmdru6kdlvjvlr3rp3snnsqx53aoo2nyal726xqueh454z4ea"',
  ContentType: 'application/octet-stream',
  Metadata: {},
  Body: <Buffer 68 6f 67 65 68 6f 67 65 0a>
}

このように返ってきます。BodyのBufferをデコードしてみると、

console.log(data.Body.toString('utf8'));

> hogehoge

とファイルの中身も取得できました。

S3 から Fleekにファイルをコピー

S3にあるオブジェクトをFleekに移動するユースケースを想定しています。

S3からs3.getObject()でデータを取得し、得られたBufferをFleekに対してs3.putObject()を実行するとコピーできますね。

例)

const AWS = require('aws-sdk');

// Fleek用
const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  accessKeyId: process.env.FLEEK_API_KEY,
  secretAccessKey: process.env.FLEEK_API_SECRET,
  endpoint: 'https://storageapi2.fleek.co',
  region: 'us-east-1',
  s3ForcePathStyle: true
});


var credentials = new AWS.SharedIniFileCredentials({profile: 'dev-cm-mori'});
AWS.config.credentials = credentials;
// S3用
const org_s3 = new AWS.S3({apiVersion: '2006-03-01'});
const params = {
  Bucket: [[bucketName]],
  Key: "[[ObjectName]]"
};

org_s3.getObject(params, function(err, data) {
   if (err) {
        console.log(err, err.stack);
   }else {
      const p = {
         Bucket: bucket,
         Key: params.Key,
         Body: data.Body
      }

      s3.putObject(p, function(err, data) {
           if (err) console.log(err, err.stack);
           else     console.log(data);
           /*
             {
                ETag: '"bafybeif5jcsicn53ih6cgsxil2hq4tksl7yutky5qyefjwj4ki3gzdekka"'
             }
           */
      });
   }
});

Webコンソールを確認してみると、

ちゃんとアップロードされていることを確認できました。

最後に

Fleek Storageに対してS3 SDKを使ってアクセスできるか試して見ました。

S3互換だと同じSDKを使ってファイルをコピーできるので、S3からのストレージの移行やバックアップに使う場合の手間が軽減されるのではないでしょうか。

参考