在NodeJS中使用MongoDB存储一些小文件(小于1MB),不使用GridFS。

32

我运行的网站后端是基于nodeJS + mongoDB的。现在,我正在实现一个系统来存储一些图标(小图片文件),这些图标需要保存在数据库中。

据我了解,不使用GridFS更合理,因为它似乎是为大文件或大量文件而设计的。由于我需要保存的每个文件都明显小于BSON最大文件大小,所以我应该能够将它们直接保存到常规文档中。

我有两个问题:

1)我的推理正确吗?将图像文件保存在常规mongo集合中,而不是使用GridFS,可以吗?这里是否有我没有考虑到的任何事情?

2)如果我的思路正确,我该如何做?我能否执行以下操作:

//assume 'things' is a mongoDB collection created properly using node-mongodb-driver

fs.readFile(pathToIconImage, function(err,image){
  things.insert({'image':image}, function(err,doc){
    if(err) console.log('you have an error! ' + err);
  });
});

我猜测有更好的方法,因为mongoDB使用BSON格式,而这里我试图在发送到数据库之前将文件保存为JSON。我也不知道这段代码是否可行(尚未尝试)。

更新-新问题

如果我有一个储存在集合中的文档,它保存了三个信息:1)名称,2)日期,和3)图像文件(上面的图标),我想将此文档发送给客户端以便显示全部三个信息,是否可能?如果不行,我想我需要使用GridFS并将文件ID保存在图像原位置。 有什么想法/建议吗?

最好的问候,感谢任何回复,
Sami


1
“Tailored” 没有具体含义。需要根据什么进行“定制”?使用GridFS会带来哪些问题? - yfeldblum
我想我会按照这里的建议去做:http://www.mongodb.org/display/DOCS/When+to+use+GridFS - thisissami
1
那里列出的任何情况实际上适用于您吗? - yfeldblum
1
我正在查看“不使用它时的几个小静态文件”(适用于我现在,但将来不会)。我想你是对的。长远来看,使用GridFS可能会更容易。但话说回来,我仍然很好奇如何在没有网格系统的情况下将小文件放入MongoDB中。 - thisissami
1
GridFS只是您数据库中的两个MongoDB集合——一个用于文件元数据,另一个用于文件的“块”(每个块为1/4 MB)。 - yfeldblum
您也可以使用任何旧集合将文件直接存储到数据库中(应使用二进制BSON数据类型)。 - yfeldblum
2个回答

38
如果你的图片确实足够小,不会对文档大小造成影响,并且你不介意稍微多进行一点处理,那么直接将它存储在集合中可能就可以了。要这样做,您需要对图像进行base64编码,然后使用mongo的BinData类型进行存储。据我所知,这将把图像保存为BSON位数组,而不是实际存储base64字符串,因此大小不会超过原始二进制图像。
在json查询中,它将显示为base64字符串,您可以使用该字符串获取二进制图像。

3
我最终使用了GridFS,但对于未来想要将图像直接存储为文档的任何人来说,这似乎是正确的方法。 - thisissami
不,我过去两个月才第一次使用mongoose。之前的三年中我使用了mongodb的nodejs原生驱动程序。 - thisissami

16

我一直在寻找同样的东西。 我知道这篇帖子很旧了,但或许我能帮助到某个人。

var fs = require('fs');
var mongo = require('mongodb').MongoClient;
var Binary = require('mongodb').Binary;

var archivobin = fs.readFileSync("vc.exe"); 
// print it out so you can check that the file is loaded correctly
console.log("Loading file");
console.log(archivobin);

var invoice = {};
invoice.bin = Binary(archivobin);

console.log("largo de invoice.bin= "+ invoice.bin.length());
// set an ID for the document for easy retrieval
invoice._id = 12345; 
  mongo.connect('mongodb://localhost:27017/nogrid', function(err, db) {
  if(err) console.log(err);
     db.collection('invoices').insert(invoice, function(err, doc){
    if(err) console.log(err);
  // check the inserted document
    console.log("Inserting file");
    console.log(doc);

    db.collection('invoices').findOne({_id : 12345}, function(err, doc){
      if (err) {
        console.error(err);
        }

      fs.writeFile('vcout.exe', doc.bin.buffer, function(err){
          if (err) throw err;
          console.log('Sucessfully saved!');
    });

    });
  });
});

有帮助 +1。更有帮助的是,如果您能展示如何保存多个文件(例如使用 multer 上传的文件),需要多次调用 readFileSync 或 readFile。 - T. Webster
这个内容很老了,但是非常感谢 +1。我对mongodb还很新,而且所有的指南都在使用express(但我不想使用它,因为我正在使用Next.js并且只想使用api路由)和gridFS。我能够完美地适应您的示例以实现我想要做的事情。 - itsseanl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接