node.jsでMongoDb GridFSへファイルアップロード

前回は、ファイルのダウンロードだったけど、今回はアップロード。

アップロードの場合、フォームをpostするのに、enctype=’multipart/form-data’とする必要があるが、node.js初心者のため、まずはここの処理でつまずいた。

ASP.netなんかだと、IFormFileなどで、簡単にファイルを切り出せるけど、node.jsではサードパーティ製のフィルタ(?)を使用する必要があるようだ。一番一般的に使われているのはmulterというものらしい。post時にこのフィルタを指定すると、ファイル以外のフィールド値とファイルを取得できる。

<form method="post" enctype="multipart/form-data">
	タイトル:<input type="text" name="title"/>
	ファイル:<input type="file" name="upfile"/>
	<input type="submit" value="アップロード"/>
</form>
var router = express.Router();
var multer = require('multer');
var upload = new multer();
var mongo = require('mongodb');
var buffer = require('buffer');

router.post('/', upload.any(), async (req,res,next) => {

	// fieldとファイルを取得
	const { fld , files } = req;

	var title = fld['title'];
	var upfile = files[0];

	・・・

ちなみに、upfile(=files[0])の内容は以下のような感じ。

{
  fieldname: 'upfile',
  originalname: 'ファイル名.タイプ',
  encoding: '7bit',
  mimetype: 'image/png',
  buffer: <Buffer 89 50 4e  ... 5926 more bytes>,
  size: 5976
}

これをMongoDbのGridFSにアップロードしたいのだが、やはりダウンロードと同じく、非同期しかサポートされていないので、以下のような関数を定義した。

	await cli.connect();
	let db = cli.db('DBName');
	let fs = new mongo.GridFSBucket(db);
	let stm = fs.openUploadStream(upfile.originalname);
	let fileid = await WriteAsync(stm,upfile.buffer);
・・・
//
//  GridFSへの書き込み(同期っぽく見えるようにしてみた)
//
async function WriteAsync(stm,data) {
  return new Promise((resolve,reject) => {
    try {
      // end()を呼ぶとfinishイベントが発生
      stm.on('finish',()=>{
        resolve(stm.id);
      });
      stm.on('error',()=>{
        reject('Write Error');
      });
      var sts = stm.write(data);
      if (!sts) {
        reject('Write Error');
      }
      // これ呼ばないと永遠に終わらない
      stm.end();
    } catch (err) {
      reject(err);
    }
  });

気を付けないといけないのは、GridFSBucketWriteStream.end()を呼び出さないと、永遠に待ち状態になってしまうところ。

色々と調べたのだが、あまり良い例が載っていなくて苦労した。

takezou について

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

コメントを残す

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

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