Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream buffer to client in Express

I have request handler to send file from MongoDB (GridFS) to client like below, but it use data variable so content is in memory. I need to make this in streaming mode and send file in chunks to client. I can't regognize how to pipe buffer to response. Look at second code - it doesn't work, but show something what i need.

Maybe it is useful: Data in GridFS is Base64 encoded, but may be changed if streaming can be more efficient.

In-Memory version

router.get('/get/:id', function(req,res){
  getById(req.params.id, function(err, fileId){
    new GridStore(db, fileId, "r").open(function(err, gridStore) {
        res.set('Content-Type', gridStore.contentType);

        var stream = gridStore.stream(true);
        var data = '';
        stream.on("data", function(chunk) {
            data += chunk;
        });
        stream.on("end", function() {                   
            res.send(new Buffer(data, 'base64'));                   
        });
    });
  });
});

Streaming mode version

router.get('/get/:id', function(req,res){
  getById(req.params.id, function(err, fileId){
    new GridStore(db, fileId, "r").open(function(err, gridStore) {
        res.set('Content-Type', gridStore.contentType);

        var stream = gridStore.stream(true);
        stream.on("data", function(chunk) {
            new Buffer(chunk, 'base64').pipe(res);
        });
        stream.on("end", function() {                   
            res.end();
        });
    });
  });
});

Update

I think I'm close to resolve this. I found this works, but does't decode from Base64:

new GridStore(db, fileId, "r").open(function(err, gridStore) {
    res.set('Content-Type', gridStore.contentType);
    gridStore.stream(true).pipe(res);
});
like image 544
marioosh Avatar asked Apr 25 '14 09:04

marioosh


People also ask

How do I stream response in Express?

You don't need a readable stream instance, just use res. write() : res. write("USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD\n"); for (var i = 0; i < 10; i++) { res.

What is difference between buffer and stream?

So what is the difference between Stream & Buffer? A buffer has a specified, definite length whereas a stream does not. A stream is a sequence of bytes that is read and/or written to, while a buffer is a sequence of bytes that is stored.

Is buffer a stream in node JS?

Buffer: In Node. js to manipulate a stream of binary data, the buffer module can be included in the code. However, the buffer is a global object in Node. js, hence it is not required to import it in code using the required method.

How do I use buffer and stream in node JS?

A buffer memory in Node by default works on String and Buffer . We can also make the buffer memory work on JavaScript objects. To do so, we need to set the property objectMode on the stream object to true . If we try to push some data into the stream, the data is pushed into the stream buffer.


2 Answers

exports.sendFile = function(db, res, fileId) {
  var grid = require('gridfs-stream');
  var gfs = grid(db, mongoose.mongo);
  var on_error = function(){
    res.status(404).end();
  };
  var readstream = gfs.createReadStream({
    filename: fileId,
    root: 'r'
  });
  readstream.on('error', function(err) {
    if (('\'' + err + '\'') === '\'Error:  does not exist\'') {
      return on_error && on_error(err);
    }
    throw err;
  });
  return readstream.pipe(res);
}
like image 147
malix Avatar answered Oct 11 '22 15:10

malix


I found a solution, but think that can be better. I use base64-stream module to decode Base64 stream. Solution below:

router.get('/get/:id', function(req,res){
    getById(req.params.id, function(err, fileId){
        new GridStore(db, fileId, "r").open(function(err, gridStore) {
            res.set('Content-Type', gridStore.contentType);
            gridStore.stream(true).pipe(base64.decode()).pipe(res);
        });
    });
}); 
like image 41
marioosh Avatar answered Oct 11 '22 13:10

marioosh