Storing data stream from POST request in GridFS, express, mongoDB, node.js
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.
Related videos on Youtube
eirik
Updated on September 26, 2022Comments
-
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 thesavePic.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 over 9 yearsThanks ,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 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 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 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 over 8 years@robertklep how can I get the details of the file stored in callback? Thanks!
-
robertklep over 8 years@vinesh you mean the meta data? See this.
-
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 :)