How to cache image read from database in Grails?

128 Views Asked by At

In our app there are two ways we serve images.

The first is through asset pipeline and second is fetching from database.

For the main company header logo we serve it from asset pipeline.

The gsp code looks like this:

<img src="${resource(dir: 'images', file: 'logo.png')}" />

which renders in html to:

<img src="/roadrace/assets/logo-addd262d2fffbdf8d868181896bf1698.png">

When the browser fetches this it is correctly memory cached as indicated in this request and marked by red box.

enter image description here

At other place where we display event image, the code look likes this:

<img src="https://.../roadrace/uploads/logos/h1FdUah7vXGqTkq.jpg?1676524906000" id="logo">

This makes get request to this controller action:

def uploads(String path) {
    FileData imageData = FileData.findByPath("/${path}")
    if (!imageData) {
        response.sendError(404)
        return
    }

    response.contentType = URLConnection.guessContentTypeFromName(path) ?: 'application/octet-stream'
    response.getOutputStream().withCloseable {out ->
        out.write(imageData.data)
        out.flush()
    }
}

You can see we are first fetching the image data using FileData domain which has data field which is of type byte[] which is written to response.

File data is defined as:

class FileData {
    String path
    byte[] data

    static constraints = {
        path blank: false, unique: true
        data nullable: false, maxSize: 16_777_215
    }
}

So here how can we add response header so that this image is also browser cached?

Since we are using images only in one place, it is best not to use cache plugins to keep the app lighter.

1

There are 1 best solutions below

0
Joaquim Manzini On

Modern browser engines have made cache of base64 image representations too. I discovered it two days ago while trying to build a browser cache using localStorage.

So, you can try to convert your byte array to a base64 representation. Take a look here how you can do it:

Base64 encoding in Java / Groovy

Chrome's returning base64 image from cache:

enter image description here