MongoDB GridFS
In this tutorial, you will learn, how you can upload, retrieve, and delete files using MongoDB GridFS.
Video tutorial:
Upload the file to MongoDB GridFS
First, in your Node JS file, you need to create an instance of your GridFS bucket. You can create as many buckets as you want.
// include MongoDB
const mongodb = require("mongodb")
// get MongoDB client
const mongoClient = mongogb.MongoClient
// connect with MongoDB server
const client = await mongoClient.connect("mongodb://localhost:27017")
const db = client.db("mongodb_gridfs")
// create GridFS bucket instance
const bucket = new mongodb.GridFSBucket(db)
- First, it includes the MongoDB module.
- Then it gets a Mongo client object that helps in connecting with the database.
- Then we connect to the server.
- After that, we set the database.
- And finally, we are creating an instance of a bucket.
You can also give your bucket a name to identify.
// create GridFS bucket instance named "myBucketName"
const bucket = new mongodb.GridFSBucket(db, {
bucketName: "myBucketName"
})
Following POST route will save the file.
// npm install fs
const fs = require("fs")
// npm install ejs
app.set("view engine", "ejs")
// npm install express-formidable
const expressFormidable = require("express-formidable")
app.use(expressFormidable())
app.post("/upload", function (request, result) {
// get input name="file" from client side
const file = request.files.file
// set file path in MongoDB GriDFS
// this will be saved as "filename" in "fs.files" collection
const filePath = (new Date().getTime()) + "-" + file.name
// read user uploaded file stream
fs.createReadStream(file.path)
// add GridFS bucket stream to the pipe
// it will keep reading and saving file
.pipe(
bucket.openUploadStream(filePath, {
// maximum size for each chunk (in bytes)
chunkSizeBytes: 1048576, // 1048576 = 1 MB
// metadata of the file
metadata: {
name: file.name, // file name
size: file.size, // file size (in bytes)
type: file.type // type of file
}
})
)
// this callback will be called when the file is done saving
.on("finish", function () {
result.send("File saved.")
})
})
Now if you check in your “mongodb_gridfs” database, you will see 2 new collections.
- fs.files
- This will save all uploaded files.
- fs.chunks
- This will save all chunks of each file with that file ID.
Fetch all files from MongoDB GridFS
The following GET route will fetch all files uploaded to MongoDB GridFS.
app.get("/", async function (request, result) {
const files = await bucket.find({
// filename: "name of file" //
})
.sort({
uploadDate: -1
})
.toArray()
result.render("index", {
files: files
})
})
Now you need to create a folder named “views” and inside that folder create a file named “index.ejs”.
Then you can loop through all files and display them in the image tag.
<% if (files) { %>
<% files.forEach(function (file) { %>
<p><%= file.filename %></p>
<img src="image/<%= file.filename %>" style="width: 200px;" />
<% }) %>
<% } %>
Right now, you will see a broken image. Now we need to create an API that will return the image as a response.
Return image as API response
app.get("/image/:filename", async function (request, result) {
// get file name from URL
const filename = request.params.filename
// get file from GridFS bucket
const files = await bucket.find({
filename: filename
})
.toArray()
// return error if file not found
if (!files || files.length == 0) {
return result.status(404).json({
error: "File does not exists."
})
}
// it will fetch the file from bucket and add it to pipe
// result response is added in the pipe so it will keep
// returning data to the client
bucket.openDownloadStreamByName(filename)
.pipe(result)
})
Now you will be able to view the image.
Delete file from MongoDB GridFS
First, you need to create a button after each file.
<% if (files) { %>
<% files.forEach(function (file) { %>
<p><%= file.filename %></p>
<img src="image/<%= file.filename %>" style="width: 200px;" />
<form action="/files/del" method="POST">
<input type="hidden" name="_id" value="<%= file._id %>" />
<button type="submit" class="btn btn-danger">Delete</button>
</form>
<% }) %>
<% } %>
Then you need to create an API in your Node JS file.
//
const ObjectId = mongodb.ObjectId
app.post("/files/del", async function (request, result) {
// get ID from data
const _id = request.fields._id
// delete file from bucket
await bucket.delete(ObjectId(_id))
// return response
result.send("File has been deleted.")
})
This will delete the file and all its chunks from the database. So that’s all for now if you face any problem in following this, kindly do let me know.
You can learn more about the grid file system from Mongo DB’s official website.