9

I have started building a REST api using expressJS. I am new to node so please bear with me. I want to be able to let users upload a file directly to Mongo's GridFS using a post to the /upload route.

From what I understand in expressJS documentation the req.files.image object is available in the route after uploading, which also includes a path and filename attribute. But how can I exactly read the image data and store it into GridFS?

I have looked into gridfs-stream but I can't tie ends together. Do I first need to read the file and then use that data for the writestream pipe? Or can I just use the file object from express and use those attributes to construct a writestream? Any pointers would be appreciated!

Maarten
  • 635
  • 2
  • 8
  • 22

1 Answers1

30

Here's a simple demo:

var express = require('express');
var fs      = require('fs');
var mongo   = require('mongodb');
var Grid    = require('gridfs-stream');
var db      = new mongo.Db('test', new mongo.Server("127.0.0.1", 27017), { safe : false });

db.open(function (err) {
  if (err) {
    throw err;
  }
  var gfs = Grid(db, mongo);
  var app = express();

  app.use(express.bodyParser());
  app.post('/upload', function(req, res) {
    var tempfile    = req.files.filename.path;
    var origname    = req.files.filename.name;
    var writestream = gfs.createWriteStream({ filename: origname });
    // open a stream to the temporary file created by Express...
    fs.createReadStream(tempfile)
      .on('end', function() {
        res.send('OK');
      })
      .on('error', function() {
        res.send('ERR');
      })
      // and pipe it to gfs
      .pipe(writestream);
  });

  app.get('/download', function(req, res) {
    // TODO: set proper mime type + filename, handle errors, etc...
    gfs
      // create a read stream from gfs...
      .createReadStream({ filename: req.param('filename') })
      // and pipe it to Express' response
      .pipe(res);
  });

  app.listen(3012);
});

I use httpie to upload a file:

http --form post localhost:3012/upload filename@~/Desktop/test.png

You can check your database if the file is uploaded:

$ mongofiles list -d test
connected to: 127.0.0.1
test.png    5520

You can also download it again:

http --download get localhost:3012/download?filename=test.png
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • This is just what I was looking for, thanks so much! Do you, by any chance, have any source for further documentation on this? – Maarten May 10 '13 at 16:15
  • There's a pretty nice handbook of how streams work [here](https://github.com/substack/stream-handbook). When you have an idea on how they work, I think most of the code I posted becomes easier to understand :) – robertklep May 10 '13 at 16:53
  • 3
    Thank you, this really helped me. Also, for those using Mongoose, the only change you need to make in the above is: var gfs = Grid(db, mongoose.mongo); – Mike Pateras Jun 13 '13 at 20:47
  • @MikePateras thanks for the tip, I'm going to be using GridFS in combination with Mongoose soon myself so it's gonna save me some looking up ;) – robertklep Jun 13 '13 at 20:50
  • I am following the code for download, but not working. any working example of full code? – vinesh Feb 25 '16 at 09:14
  • @vinesh it's an old answer, perhaps create a new question with your exact problems? – robertklep Feb 25 '16 at 09:15
  • @robertklep Good suggestion. I have asked question here. http://stackoverflow.com/questions/35623596/mean-serve-file-from-gridfs – vinesh Feb 25 '16 at 09:46
  • @robertklep , Where can we configure the name of the table in test ? cause the deault is table fs.files and fs.files. –  Sep 26 '19 at 08:00
  • @Mr.RajivKumar `gfs.createWriteStream({ filename: origname, root : 'your_table_name' })` (that would create `your_table_name.files` and `your_table_name.chunks`). See [the documentation](https://github.com/aheckmann/gridfs-stream#createwritestream). – robertklep Sep 26 '19 at 08:04
  • Sir can you please open a chat ? I really wanted to ask question on you since you are expert in grid fs –  Sep 26 '19 at 08:06
  • I am using keystone JS there already a connection that is stablished , how can we get rid of var db = new mongo.Db('test', new mongo.Server("127.0.0.1", 27017), { safe : false }); and also db.open –  Sep 26 '19 at 08:21
  • so that we will no longer be defining the connections –  Sep 26 '19 at 08:24
  • @Mr.RajivKumar I don't have time to chat right now, sorry :( But it seems to me that you should post a new question where you explain your situation and what you want to achieve. – robertklep Sep 26 '19 at 08:27
  • I am using my stablished connecion but i am receiving grid.mongo.ObjectID is not a constructor –  Sep 26 '19 at 08:31
  • d you have a complete sample on getting the file like setting mime type + filename, handle errors, etc... –  Sep 27 '19 at 04:14
  • @robertklep , how can we avoid duplicates in mongo grid fs Sir? –  Sep 30 '19 at 01:48
  • @Mr.MarkTawin please stop asking your questions in comments. Create a new question here on StackOverflow. – robertklep Sep 30 '19 at 06:32