如何在Grails中缓存从数据库读取的图像?

huangapple go评论71阅读模式
英文:

how to cache image read from database in grails?

问题

在我们的应用程序中,我们有两种方式提供图像。

第一种方式是通过资源管道(asset pipeline),第二种方式是从数据库获取。

对于主公司标头标志,我们是通过资源管道提供的。

GSP(Groovy Server Pages)代码如下:

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

它在 HTML 中呈现为:

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

当浏览器获取这个图像时,它会被正确地存储在内存缓存中,如此请求所示,并由红框标出。

在其他地方,当我们显示事件图像时,代码如下:

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

这会向控制器动作发送 GET 请求:

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()
    }
}

您可以看到,我们首先使用FileData领域来获取图像数据,该领域具有类型为byte[]的data字段,然后将其写入响应。

文件数据的定义如下:

class FileData {
    String path
    byte[] data

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

那么,如何添加响应标头,以便该图像也被浏览器缓存?

由于我们仅在一个地方使用图像,最好不使用缓存插件,以使应用程序更轻量。

谢谢您的帮助!

英文:

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

&lt;img src=&quot;${resource(dir: &#39;images&#39;, file: &#39;logo.png&#39;)}&quot; /&gt;

which renders in html to

&lt;img src=&quot;/roadrace/assets/logo-addd262d2fffbdf8d868181896bf1698.png&quot;&gt;

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

如何在Grails中缓存从数据库读取的图像?

at other place where we display event image

the code look likes this

&lt;img src=&quot;https://.../roadrace/uploads/logos/h1FdUah7vXGqTkq.jpg?1676524906000&quot; id=&quot;logo&quot;&gt;

this makes get request to this controller action

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

	response.contentType = URLConnection.guessContentTypeFromName(path) ?: &#39;application/octet-stream&#39;
	response.getOutputStream().withCloseable {out -&gt;
		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.

Thanks for the help!

答案1

得分: 1

现代浏览器引擎也对base64图像表示进行了缓存。我在两天前尝试使用localStorage构建浏览器缓存时发现了这一点。

因此,您可以尝试将字节数组转换为base64表示。请看这里,您可以了解如何做到:

https://stackoverflow.com/questions/4188406/base64-encoding-in-java-groovy

Chrome从缓存返回的base64图像:

进入图像描述

英文:

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:

https://stackoverflow.com/questions/4188406/base64-encoding-in-java-groovy

Chrome's returning base64 image from cache:

enter image description here

huangapple
  • 本文由 发表于 2023年2月19日 15:09:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75498531.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定