31

I run a website that runs on a backend of nodeJS + mongoDB. Right now, I'm implementing a system to store some icons (small image files) that will need to be in the database.

From my understanding, it makes more sense NOT to use GridFS, since that seems to be tailored for either large files or large numbers of files. Since every file that I need to save will be well under the BSON maximum file size, I should be able to save them directly into a regular document.

I have 2 questions:

1) Is my reasoning correct? Is it ok to save image files within a regular mongo collection, as opposed to with GridFS? Is there anything I'm not considering here that I should be?

2) If my thought process is sound, how do I go about doing this? Could I do something like the following:

//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);
  });
});

I'm guessing that there's probably a better way to do this, since mongoDB uses BSON and here I'm trying to save a file in JSON before I send it off to the database. I also don't know if this code will work (haven't tried it).

UPDATE - New Question

If I have a document within a collection that has three pieces of information saved: 1) a name, 2) a date, and 3) an image file (the above icon), and I want to send this document to a client in order to display all three, would this be possible? If not, I guess I'd need to use GridFS and save the fileID in place of the image itself. Thoughts/suggestions?

Best, and thanks for any responses,
Sami

thisissami
  • 15,445
  • 16
  • 47
  • 74
  • 1
    "Tailored" means nothing. Tailored *how*? What problems will using GridFS for this task present? – yfeldblum Jul 11 '12 at 22:26
  • I guess I'm going by the suggestions here: http://www.mongodb.org/display/DOCS/When+to+use+GridFS – thisissami Jul 11 '12 at 22:29
  • 1
    Do any of the cases listed there actually apply to you? – yfeldblum Jul 11 '12 at 22:33
  • 1
    I was looking at the "few small static files" (under when not to use it) which applies to me for now, but won't in the future. i guess you're right. it'll probably be easier just to use GridFS in the long run. but that said, I am still curious how I would go about putting a small file into MongoDB without the grid system. – thisissami Jul 11 '12 at 22:44
  • 1
    GridFS is just two MongoDB collections in your database - one for file metadatas, and one for the "chunks" of your file (each chunk is 1/4 of a MB). – yfeldblum Jul 11 '12 at 22:49
  • You can also just stick files in your database using any old collection (you should use the binary BSON datatype for this). – yfeldblum Jul 11 '12 at 22:50

2 Answers2

38

If your images truly are small enough to not be a problem with document size and you don't mind a little amount of extra processing, then it's probably fine to just store it directly in your collection. To do that you'll want to base64 encode the image, then store it using mongo's BinData type. As I understand it, that will then save it as a BSON bit array, not actually store the base64 string, so the size won't grow larger than your original binary image.

It will display in json queries as a base64 string, which you can use to get the binary image back.

Tim Gautier
  • 29,150
  • 5
  • 46
  • 53
  • 3
    I ended up using GridFS, but for anybody looking at this in the future that wants to store images directly as documents, this seems to be the right approach. – thisissami Nov 07 '12 at 01:41
  • nope - I only used mongoose for the first time in the past 2 months. used the mongodb nodejs native driver for the previous 3 years. – thisissami Dec 17 '14 at 00:31
16

I have been looking for the same thing. I know this post is old , but perhaps i can help someone out there.

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!');
    });

    });
  });
});
uajov6
  • 413
  • 7
  • 13
  • Is helpful +1. More helpful is if you could show how to save multiple files (e.g. uploaded with [multer](https://github.com/expressjs/multer), where multiple calls to [readFileSync](https://nodejs.org/api/fs.html#fs_fs_readfilesync_file_options) or readFile are required. – T. Webster Jun 17 '16 at 00:36
  • this is way old but thank you so much +1. I'm new to mongodb and every guide out there is using express (which I didn't want to use because I'm using Next.js and wanted to just use the api routes) and gridFS. I was able to adapt your example perfectly for what I wanted to do. – itsseanl Apr 28 '20 at 19:15