In the tutorial, we show you how to build a NodeJS web-application that uses stream-based GridFS APIs with Mongoose to upload/download files to MongoDB.
Related posts:
– NodeJS – use Mongoose to save Files/Images to MongoDB
– Crud RestAPIs with NodeJS/Express, MongoDB using Mongoose
Contents
NodeJS MongoDB GridFS
The MongoDB Node.js driver supports a stream-based API for GridFS, so we can .pipe()
directly from file streams to MongoDB.
We create a web-application that uses GridFS APIs to upload/download files:
Upload File
var express = require('express'); var mongoose = require('mongoose'); var gridfs = require('gridfs-stream'); var fs = require('fs'); var app = express(); mongoose.connect('mongodb://localhost:27017/test') mongoose.Promise = global.Promise; gridfs.mongo = mongoose.mongo; var connection = mongoose.connection; connection.once('open', () => { ... // Upload a file from loca file-system to MongoDB app.get('/api/file/upload', (req, res) => { var filename = req.query.filename; var writestream = gfs.createWriteStream({ filename: filename }); fs.createReadStream(__dirname + "/uploads/" + filename).pipe(writestream); writestream.on('close', (file) => { res.send('Stored File: ' + file.filename); }); });
Download File
... app.get('/api/file/download', (req, res) => { // Check file exist on MongoDB var filename = req.query.filename; gfs.exist({ filename: filename }, (err, file) => { if (err || !file) { res.status(404).send('File Not Found'); return } var readstream = gfs.createReadStream({ filename: filename }); readstream.pipe(res); }); });
Delete File
... // Delete a file from MongoDB app.get('/api/file/delete', (req, res) => { var filename = req.query.filename; gfs.exist({ filename: filename }, (err, file) => { if (err || !file) { res.status(404).send('File Not Found'); return; } gfs.remove({ filename: filename }, (err) => { if (err) res.status(500).send(err); res.send('File Deleted'); }); }); });
Meta Information
... app.get('/api/file/meta', (req, res) => { var filename = req.query.filename; gfs.exist({ filename: filename }, (err, file) => { if (err || !file) { res.send('File Not Found'); return; } gfs.files.find({ filename: filename }).toArray( (err, files) => { if (err) res.send(err); res.json(files); }); }); });
Practice
In the tutorial, we create a NodeJS project as below structure:
/NodeJS-GridFS-MongDB /node_modules /uploads jsa_about.txt jsa_cover.png jsa_vision.png package.json server.js
Setting up NodeJS project
NodeJS-GridFS-MongDB>npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (nodejs-gridfs-mongdb) version: (1.0.0) description: Using GridFS-Stream to upload/download large-files to MongoDB with Mongoose entry point: (index.js) server.js test command: git repository: keywords: NodeJS, GridFS, GridFS-Stream, MongoDB, Express, Mongoose author: grokonez.com license: (ISC) About to write to C:\nodejs\NodeJS-GridFS-MongDB\package.json: { "name": "nodejs-gridfs-mongdb", "version": "1.0.0", "description": "Using GridFS-Stream to upload/download large-files to MongoDB with Mongoose", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "NodeJS", "GridFS", "GridFS-Stream", "MongoDB", "Express", "Mongoose" ], "author": "grokonez.com", "license": "ISC" } Is this ok? (yes) yes
-> Install Express, GridFS-Stream, Mongoose:
npm install express gridfs-stream mongoose --save
-> See package.json file:
{ "name": "nodejs-gridfs-mongdb", "version": "1.0.0", "description": "Using GridFS-Stream to upload/download large-files to MongoDB with Mongoose", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "NodeJS", "GridFS", "GridFS-Stream", "MongoDB", "Express", "Mongoose" ], "author": "grokonez.com", "license": "ISC", "dependencies": { "express": "^4.16.3", "gridfs-stream": "^1.1.1", "mongoose": "^5.1.2" } }
Implement Server.js
var express = require('express'); var mongoose = require('mongoose'); var gridfs = require('gridfs-stream'); var fs = require('fs'); var app = express(); /* Make a MongoDB connection */ mongoose.connect('mongodb://localhost:27017/test') mongoose.Promise = global.Promise; gridfs.mongo = mongoose.mongo; /* Check MongoDB connection */ var connection = mongoose.connection; connection.on('error', console.error.bind(console, 'connection error:')); connection.once('open', () => { var gfs = gridfs(connection.db); app.get('/', (req, res) => { res.send('Download/Upload GridFS files to MongoDB
- by grokonez.com'); }); // Upload a file from loca file-system to MongoDB app.get('/api/file/upload', (req, res) => { var filename = req.query.filename; var writestream = gfs.createWriteStream({ filename: filename }); fs.createReadStream(__dirname + "/uploads/" + filename).pipe(writestream); writestream.on('close', (file) => { res.send('Stored File: ' + file.filename); }); }); // Download a file from MongoDB - then save to local file-system app.get('/api/file/download', (req, res) => { // Check file exist on MongoDB var filename = req.query.filename; gfs.exist({ filename: filename }, (err, file) => { if (err || !file) { res.status(404).send('File Not Found'); return } var readstream = gfs.createReadStream({ filename: filename }); readstream.pipe(res); }); }); // Delete a file from MongoDB app.get('/api/file/delete', (req, res) => { var filename = req.query.filename; gfs.exist({ filename: filename }, (err, file) => { if (err || !file) { res.status(404).send('File Not Found'); return; } gfs.remove({ filename: filename }, (err) => { if (err) res.status(500).send(err); res.send('File Deleted'); }); }); }); // Get file information(File Meta Data) from MongoDB app.get('/api/file/meta', (req, res) => { var filename = req.query.filename; gfs.exist({ filename: filename }, (err, file) => { if (err || !file) { res.send('File Not Found'); return; } gfs.files.find({ filename: filename }).toArray( (err, files) => { if (err) res.send(err); res.json(files); }); }); }); var server = app.listen(8081, () => { var host = server.address().address var port = server.address().port console.log("App listening at http://%s:%s", host, port); }); });
Run & Check results
– Upload files:
localhost:8081/api/file/upload?filename=jsa_about.txt
localhost:8081/api/file/upload?filename=jsa_vision.png
localhost:8081/api/file/upload?filename=jsa_cover.png
-> Check MongoDB GridFS:
> db.fs.files.find() { "_id" : ObjectId("5b06683ff905a60eac1ece4d"), "filename" : "jsa_about.png", "contentType" : "binary/octet-stream", "length" : 125872, "chunkSize" : 261120, "uploadDate" : ISODate("2018-05-24T07:22:42.747Z"), "aliases" : null, "metadata" : null, "md5" : "176eae627f5ecde3ecb2d9d5694a4f53" } { "_id" : ObjectId("5b066888f905a60eac1ece4f"), "filename" : "jsa_vision.png", "contentType" : "binary/octet-stream", "length" : 125872, "chunkSize" : 261120, "uploadDate" : ISODate("2018-05-24T07:23:52.749Z"), "aliases" : null, "metadata" : null, "md5" : "176eae627f5ecde3ecb2d9d5694a4f53" } { "_id" : ObjectId("5b06689df905a60eac1ece51"), "filename" : "jsa_cover.png", "contentType" : "binary/octet-stream", "length" : 59632, "chunkSize" : 261120, "uploadDate" : ISODate("2018-05-24T07:24:13.649Z"), "aliases" : null, "metadata" : null, "md5" : "e3ea70be7ca215d8ff20adce5716d620" }
> db.fs.chunks.count() 3
> db.fs.chunks.find({}, { data: 0 }) { "_id" : ObjectId("5b066842f905a60eac1ece4e"), "files_id" : ObjectId("5b06683ff905a60eac1ece4d"), "n" : 0 } { "_id" : ObjectId("5b066888f905a60eac1ece50"), "files_id" : ObjectId("5b066888f905a60eac1ece4f"), "n" : 0 } { "_id" : ObjectId("5b06689df905a60eac1ece52"), "files_id" : ObjectId("5b06689df905a60eac1ece51"), "n" : 0 }
– Download File request: http://localhost:8081/api/file/download?filename=jsa_cover.png
– Get meta information of files: http://localhost:8081/api/file/meta?filename=jsa_cover.png
– Delete a file request: http://localhost:8081/api/file/delete?filename=jsa_cover.png
-> Then check MongoDB after the deletion:
> db.fs.files.find() { "_id" : ObjectId("5b06683ff905a60eac1ece4d"), "filename" : "jsa_about.png", "contentType" : "binary/octet-stream", "length" : 125872, "chunkSize" : 261120, "uploadDate" : ISODate("2018-05-24T07:22:42.747Z"), "aliases" : null, "metadata" : null, "md5" : "176eae627f5ecde3ecb2d9d5694a4f53" } { "_id" : ObjectId("5b066888f905a60eac1ece4f"), "filename" : "jsa_vision.png", "contentType" : "binary/octet-stream", "length" : 125872, "chunkSize" : 261120, "uploadDate" : ISODate("2018-05-24T07:23:52.749Z"), "aliases" : null, "metadata" : null, "md5" : "176eae627f5ecde3ecb2d9d5694a4f53" }
Sourcecode
To run below sourcecode, follow the guides:
step 0: download & extract zip file -> we have a folder ‘NodeJS-GridFS-MongDB’
step 1: cd NodeJS-GridFS-MongDB
step 2: npm install express gridfs-stream mongoose –save
step 3: node server.js
-> Sourcecode:
Last updated on April 13, 2019.
Im sorry but how about the model for mongodb? How u could save the files without creating a model for database?
yes
db.fs.files.find()
db.fs.chunks.find()
These two models are created by Gridfs