node.jsでMongoDB GridFSからファイル取得

node.jsでMongoDB上のGridFSからファイルをダウンロードするのに手間取ったので、メモ。

やりたかったのは、MongoDB上のGridFSからイメージファイルデータを取得して、データURLを作りたかっただけだけど、node.jsのMongoDB DriverのGridFSBucketReadStreamのreadメソッドが、非同期動作しかできないようで、色々苦労した・・・

結局、read周辺の部分をpromiseを使用して、async funcitonにする事でとりあえず、一見落着。

var mongo = require('mongodb');
var buffer = require('buffer');
・・・
let fs = new mongo.GridFSBucket(db);
// ObjectIdを使用してGridFSBucketReadStreamを得る
var stm = fs.openDownloadStream(ObjectId("xxx・・・"));
// 同期的にイメージファイルデータ取得
var body = await ReadAsync(stm);
var imgUrl =  'data:image/jpeg;base64,' + buffer.Buffer.from(body).toString('base64');

//
// GridFSBucketReadStreamから同期的に(見えるように)データ取得
//	戻り値:Promise<Buffer>
//
async function ReadAsync(stm) {
  return new Promise((resolve,reject) => {
    try {
      var totalsize = 0; // 読み取ったトータルサイズ
      var chunks = [];  // 読み取ったchunk
      // データ取得時コールバック定義
      stm.on('data',
        (v) => {
          // 読込んだデータ(chunk)を保存
          var buf = buffer.Buffer.from(v);
          chunks.push(buf);
          totalsize += buf.length;
        }
      );
      // データ終了時コールバック定義
      stm.on('end',
        () => {
          // 結合先のBufferを作成
          var ximage = buffer.Buffer.alloc(totalsize);
          // 全chunkの結合
          var offset = 0;
          for(var i=0; i < chunks.length; i++) {
            chunks[i].copy(ximage,offset);
            offset += chunks[i].length;
          }
          // 読込んだデータを返す
          resolve(ximage);
        }
      );
      // 読込可時コールバック定義
      stm.on('readable',
        // 読込開始
        ()=> stm.read()
      );
    } catch (err) {
      reject(err);
    }
  });
}

解決するまでにちょっと時間が掛かったなぁ・・・

これが正解かどうかは分からないけど、取敢えず動いているからいいや。

正規のライブラリにもawait stm.read()で呼び出させるようなメソッド用意しておいて欲しいな。

takezou について

ソフトウェア開発会社(ITと言う言葉は大嫌い)で働く、元技術者。 未だに、社内システム位は作ってますが・・・ プログラミング言語はC#が好き。 好きなことだけ拾って投稿しているので、内容にはあまり期待しないでねw
カテゴリー: MongoDB, node.js, 技術系 パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください