Upload files to MongoDB GridFS with Express

abskmj

abskmj

Posted on October 1, 2020

Upload files to MongoDB GridFS with Express

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
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.

Related