Grails:在gsp中显示创build的图像
我对Grails很陌生,所以这个问题可能是一个非常简单的答案。 我试图在gsp中显示一个dynamic创build的图像。 图像不存储在数据库中,它是在控制器中实时创build的。
我基本上有一个gsp有一个forms,接受一组用户input(requestGraph.gsp)。 提交表单后,参数将被发送到控制器中的一个displayGraph动作,该动作完全从Grails之外的数据库查询信息,并使用JFreeChart库创build图表。 我想在displayGraph.gsp或类似的东西中显示这个图像。
所以基本上在requestGraph.gsp内我有一个片段类似于:
<g:form action="displayGraph"> <!-- ... bunch of labels and boxes --> <g:submitButton name="displayGraph" value="Display Graph" /> </g:form>
在控制器内,我有这样的东西:
def requestGraph = {} def displayGraph = { //... code that uses params to make an image byte array and assigns to var img return [image : img] }
在displayGraph.gsp中:
<body> <h1>Graph Title</h1> <!-- ??? How to dislpay image? --> </body>
我试图通过displayGraph动作直接将图像传输到输出stream。 这工作,但是然后我失去了displayGraph.gsp所有页面格式的控制。
我发现的大多数教程都创build了一个专门的操作来将图像传输到输出stream,然后使用标记调用该操作。 问题是我的图像没有存储在数据库中,我看不到传递图像字节数组(甚至表单参数)来创build/渲染图像的方法。 有人可以帮我吗? 谢谢。
如果将字节写入输出stream,则可以将控制器/操作视为GSP中图像的来源。 这是一个快速,未经testing的例子:
// controller action def displayGraph = { def img // byte array //... response.setHeader('Content-length', img.length) response.contentType = 'image/png' // or the appropriate image content type response.outputStream << img response.outputStream.flush() }
然后你可以像这样在<img>
标签的src
中访问你的图片:
<img src="${createLink(controller: 'myController', action: 'displayGraph')}"/>
更新 :
再次阅读您的问题后,这可能会或可能不会工作 – 看起来您可能会显示图表作为表单提交的结果。 这只会在你将状态存储在服务器的某处(而不是从提交表单的请求中获取)的情况下起作用。 如果你在服务器上存储足够的状态来生成graphics,那么你必须提供一些额外的参数给你的控制器来获得正确的图像,例如src="${g.link(controller: 'myController', action: 'displayGraph', params: ['id': 1234])}"
,其中id是您如何检索graphics状态。
我的build议其实有两个部分。
1)使用上面Rob推荐的解决scheme来生成图表工件, 但是将其保存到具有唯一标识符的静态文件中,该文件作为表单提交的响应的一部分传回,然后渲染图表并没有不同,其他图像。
我build议标识符是通过表单提交的参数params来构造的,所以它们可以作为一个caching机制来再次呈现图表而不用重build它
2)创build一个服务,也许是一个Quartz服务 ,定期清理为应用程序创build的静态图表
以下代码在Grails 2.x中可用。
HomeController.groovy
class HomeController { def index() { } def viewImage(){ def file = new File(params.title) def img = file.bytes response.contentType = 'image/png' // or the appropriate image content type response.outputStream << img response.outputStream.flush() } }
意见/家/ index.jsp的
<%@ page contentType="text/html;charset=ISO-8859-1" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> <meta name="layout" content="main"/> <title>View Image</title> </head> <body> <div class="body"> <img src="<g:createLink controller="home" action="viewImage" params="[title: 'C:/pictures/myimage.png']"/>"/> </div> </body> </html>
只是@罗布的回答改进:
另一个更好的select,你可以直接从你的控制器的动作渲染图像:
// controller action def displayGraph = { def img // a byte[], File or InputStream render(file: img, contentType: 'image/png') }
另见: http : //grails.org/doc/latest/ref/Controllers/render.html
我相信这不是关于Grails,而是关于HTML。 你可以:
- 使pipe道图像接受某些参数的专用动作,并在该动作中生成图像;
-
将base64编码embedded到HTML中,如下所示:
<img src =“data:image / gif; base64,R0lGODlhUAAPAKIAAAsL … etc …”alt =“wow”/>
由于任何原因,上述解决scheme不会显示任何图像。 我用了:
<img src='${createLink(controller: "myController", action: "displayGraph")}' />
代替。
我使用FileUploadService来保存图像文件在Grails中。如果您从目录手段获取图像,试试这个:
<img style="height: 120px;width: 102px;"src="${resource(dir:'personImages', file: personalDetailsInstance.id + '.png')}" />
你的gsp:
<img src="${createLink(controller: "image", action: "draw")}" />
你的控制器:
def draw() { byte[] imageInBytes = imageService.getImageInBytes() //should return byte array response.with{ setHeader('Content-length', imageInBytes.length.toString()) contentType = 'image/jpg' // or the appropriate image content type outputStream << imageInBytes outputStream.flush() } }