Storing data stream from POST request in GridFS, express, mongoDB, node.js

17,044

Solution 1

gridfs-stream makes that pretty easy:

// `gfs` is a gridfs-stream instance
app.post('/picture', function(req, res) {
  req.pipe(gfs.createWriteStream({
    filename: 'test'
  }));
  res.send("Success!");
});

Solution 2

while @robertklep's answer is correct, I would like to add something to his answer. This code shows how you can send back the stored file's metadata.

app.post('/picture', function(req, res) {
  req.pipe(gfs.createWriteStream({
    filename: 'test'
  }).on('close', function(savedFile){
    console.log('file saved', savedFile);
    return res.json({file: savedFile});
  }));
})  

Solution 3

This worked for me with mongoose:

 var gfs = Grid(mongoose.connection.db, mongoose.mongo);
    var writeStream = gfs.createWriteStream({
        filename: name,
        mode: 'w',
        content_type: 'video/mp4'
    });
    writeStream.on('close', function() {
        console.log('close event');
    });

    fs.createReadStream('uploads/' + name + '/' + name + '.mp4').pipe(writeStream);
    console.log('stream.write: ' + name + '/' + name + '.mp4');

I am struggling a couple of days with getting the video on client side browser. That is what I tried so far:

var readstream = gfs.createReadStream({
        filename: file.filename
    });

    readstream.on('data', function(data) {
        res.write(data);
        console.log(data);
    });

    readstream.on('end', function() {
        res.end();        
    });

    readstream.on('error', function (err) {
        console.log('An error occurred!', err);
        throw err;
    });

My Data on MongoDB side looks like:

db.fs.chunks.find() { "_id" : ObjectId("5757e76df14741bf0391aaca"), "files_id" : ObjectId("5757e76df14741bf0391aac8"), "n" : 0, "data" : BinData(0,"AAAAIGZ0eXBpc29....

And the contentType is 'video/mp4':

logging on browser side prints this:

Object { 0: "�", 1: "�", 2: "�", 3: " ", 4: "f", 5: "t", 6: "y", 7: "p", 8: "i", 9: "s", 85003 more… }

Could someone please save my live? I hope you do not see my post as not convenient in this place.

Share:
17,044

Related videos on Youtube

eirik
Author by

eirik

Updated on September 26, 2022

Comments

  • eirik
    eirik over 1 year

    I am trying to figure out how I can post an image directly to GridFS without storing it anywhere on the server as a temporary file first.

    I am using Postman (chrome ext.) to post a file, and I manage to store this post as a file using:

    req.pipe(fs.createWriteStream('./test.png'));
    

    I am also able to store directly to GridFS from a readStream when the readStream is created from a file on the server. (see code)

    I have the following files, saveFromReq.js which listens for the POST and basically just passes this on to the savePic.js.

    saveFromReq.js:

    var express = require('express');
    var app = express();
    var savePic = require('./savePic');
    var fs = require('fs');
    var GridStore = require('mongodb').GridStore;
    var pic = './square.png';
    var picID;
    
    
    
    //When the following
    
     //var pic = fs.createReadStream('./square.png', {autoClose: true});
    
    //is not commented out, and 'req' is replaced with 'pic' in the savePic function,
    //the file square.png is stored correctly to GridFS
    
    app.post('/picture', function(req, res){
    
        savePic(req, function(id){});
        res.writeHead(200, {'Content-Type': 'text' });
        res.end("Sucsess!\n");
    
    });
    
    app.listen(process.env.PORT || 3413);
    

    savePic.js:

    var savePic = function(req, callback){
    
    
    var Db = require('mongodb').Db,
        MongoClient = require('mongodb').MongoClient,
        Server = require('mongodb').Server,
        ReplSetServers = require('mongodb').ReplSetServers,
        ObjectID = require('mongodb').ObjectID,
        Binary = require('mongodb').Binary,
        GridStore = require('mongodb').GridStore,
        Grid = require('mongodb').Grid,
        Code = require('mongodb').Code,
        BSON = require('mongodb').pure().BSON,
        assert = require('assert');
        fs = require('fs');
    
        //When the following 
    
          //req.pipe(fs.createWriteStream('./test.png'));
    
        //is not commented out, the correct image is stored to test.png, and 
        //the sequence after req.on("data"... starts
        //(That sequence does not start at all when this is commented out..)
    
    var fileId = new ObjectID();
    var db = new Db('testDB', new Server('localhost', 27017));
    // Establish connection to db
    db.open(function(err, db) {
    
    
      var gridStore = new GridStore(db, 'test', 'w');
    
      //open 
      gridStore.open(function(err, gridStore) {
        console.log("opened");
    
    
        req.on("data", function (data) {
            console.log("data recieved");
                gridStore.write(data, function (err, gridStore) {
                    if (err) {
                        console.log("error writing file");
                    }
                });
            });
         req.on("end", function () {
                gridStore.close(function (err, gridStore) {
                    if (!err) {
                        console.log("The file has been stored to database.");
                        db.close();
                    }
                });
            });
               req.pipe(gridStore);
    
    
          });
    
    
    
    
    });
    callback(fileId);
    };
    module.exports = savePic;
    

    Any help would be greatly appreciated!

  • hussainb
    hussainb over 9 years
    Thanks ,This works. Also, can you please tell how to handle 'file type multiple' or multiple file controls in a form. and how to get the original file name from the post.
  • JN_newbie
    JN_newbie about 9 years
    @robert, I am new to gridfs. Can you please tell me what is the filename in createWriteStream. What will be the case if i want to store bytes? Should I create a new question for it?
  • robertklep
    robertklep about 9 years
    @Java_NewBie the filename is documented here. Basically, it's an (optional) identifier for the GridFS document that you're creating (so you can access that document not just through it's unique _id property but also through a human-readable string). You can make this string anything you want.
  • JN_newbie
    JN_newbie about 9 years
    @robertklep Thankyou robert. I am trying to use the above code to store video( bytes) which will send from the device in gridfs with your answer. but I am struggling to store it. I need an understanding. I have posted the question on the separate thread, but someone navigated to this link as duplicate.Thankyou
  • vinesh
    vinesh over 8 years
    @robertklep how can I get the details of the file stored in callback? Thanks!
  • robertklep
    robertklep over 8 years
    @vinesh you mean the meta data? See this.
  • vinesh
    vinesh over 8 years
    @robertklep Yup, I figured out to find the metadata for the stored file. your answer helped me to solve problem. Thanks :)