Upload files to MongoDB GridFS with Express
abskmj
Posted on October 1, 2020
Create express based APIs to upload and download files to and from MongoDB GridFS.
GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16 MB.
Install Dependencies
-
express
to create the APIs -
multer
to handle multi-part file uploads -
mongoose
to manage connections to MongoDB -
gridfile
to manage interactions with GridFS
GridFile Mongoose Model
GridFile is a reusable Mongoose Schema for MongoDB GridFS.
// gridfile.model.js
const mongoose = require('mongoose')
const schema = require('gridfile')
module.exports = mongoose.model('GridFile', schema)
Multer Middleware
Multer will parse multipart/form-data
request and the uploaded files will be accessible as req.files
const multer = require('multer')
const upload = multer({ dest: path.join(__dirname, '.') })
Upload File API
API uses the multer middleware and GridFile model to upload files to GridFS.
app.post('/v1/files', upload.any(), async (req, res, nxt) => {
try {
// uploaded file are accessible as req.files
if (req.files) {
const promises = req.files.map(async (file) => {
const fileStream = fs.createReadStream(file.path)
// upload file to gridfs
const gridFile = new GridFile({ filename: file.originalname })
await gridFile.upload(fileStream)
// delete the file from local folder
fs.unlinkSync(file.path)
})
await Promise.all(promises)
}
res.sendStatus(201)
} catch (err) {
nxt(err)
}
})
List Files API
API returns information about uploaded files.
app.get('/v1/files', async (req, res, nxt) => {
try {
const files = await GridFile.find({})
res.json(files)
} catch (err) {
nxt(err)
}
})
Sample response
[
{
"aliases": [],
"_id": "5f6850023516552ad21d0007",
"length": 7945,
"chunkSize": 261120,
"uploadDate": "2020-09-21T07:02:26.389Z",
"filename": "attachment.pdf",
"md5": "fa7d7e650b2cec68f302b31ba28235d8"
}
]
Download File API
API returns the file from the GridFS using its id.
app.get('/v1/files/:id/:name', async (req, res, nxt) => {
try {
const { id, name } = req.params
const gridFile = await GridFile.findById(id)
if (gridFile) {
res.attachment(name)
gridFile.downloadStream(res)
} else {
// file not found
res.status(404).json({ error: 'file not found' })
}
} catch (err) {
nxt(err)
}
})
Sample Request URL
/v1/files/5f6850023516552ad21d0007/attachment.pdf
A working codebase for reference is available at gist.github.com
💖 💪 🙅 🚩
abskmj
Posted on October 1, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.