How to cache .jpg in memory for Express middleware?

Viewed 172

I have this Express middleware to deliver thumbnails (.jpeg) on demand:

    app.get('/thumb/:index', function(req, res){
        var index = req.params.index

        if (!index) return res.status(404).send()

        var jpeg = PATH.join('./thumbs/', index, '.jpg')
        res.status(200).sendFile(jpeg)
    })

This answer shows how to do it when using .static but I'm not sure how to use it on a app.get middleware.

The goal is to cache all jpeg thumbnails on memory to speed up response and avoid physical disk acccess all the time.

1 Answers

Here is a way that works and that I could come up with in less than 10 minutes.

The infamous use of a global variable is applicable here. The const cacheMap is a Map that will cache the binary content in memory using the index const as its key.

It is probably not the best implementation of all, but it is better than many possible solutions and it works.

Don't forget to remove/comment the console.log calls that are there just for your to see that the follow-up requests don't print the "reading file ..." string

const path = require('path')
const fs = require('fs')
const app = require('express')()
const cacheMap = new Map()

app.get('/thumb/:index', async function (req, res) {
  const { index } = req.params

  if (!index) return res.status(404).send()

  const jpeg = path.join(__dirname, 'thumbs', `${index}.jpg`)
  if (!cacheMap.has(index)) {
    console.log('reading file', jpeg)
    cacheMap.set(index, await fs.promises.readFile(jpeg))
  }
  console.log({ index })

  return res
    .header('content-type', 'image/jpeg')
    .status(200)
    .send(cacheMap.get(index))
})
Related