Grails: отображение созданного изображения в gsp
Я очень новичок в Grails, поэтому, наверное, очень простой ответ на этот вопрос. Я пытаюсь отобразить динамически созданное изображение в gsp. Изображение НЕ хранится в базе данных, оно создано "на лету" в контроллере.
У меня есть один gsp, который имеет форму, которая принимает набор пользовательских входов (requestGraph.gsp). При отправке формы параметры отправляются в действие displayGraph в контроллере, который запрашивает информацию из базы данных полностью за пределами Grails и создает диаграмму с использованием библиотеки JFreeChart. Я хотел бы отобразить это изображение в 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. Это работает, но затем я теряю контроль над всем форматированием страницы в displayGraph.gsp.
Большинство учебных пособий, которые я нашел, создают выделенное действие, чтобы передать изображение в выходной поток, а затем вызвать это действие с помощью тега. Проблема в том, что мое изображение не хранится в базе данных, и я не вижу способа передать массив байтов изображения (или даже параметры формы) для создания/рендеринга изображения. Может ли кто-нибудь помочь мне в этом? Спасибо.
Ответы
Ответ 1
Если вы записываете байты в выходной поток, вы можете рассматривать контроллер/действие как источник изображения в своем GSP. Вот быстрый, непроверенный пример:
// 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()
}
Затем вы можете получить доступ к своему изображению в теге src
тега <img>
следующим образом:
<img src="${createLink(controller: 'myController', action: 'displayGraph')}"/>
Update:
После повторного чтения вашего вопроса это может работать или не работать - похоже, вы можете отображать график в результате отправки формы. Это будет работать только в том случае, если вы где-то сохраняете состояние на сервере (вместо того, чтобы просто получать его с одного запроса, где представлена форма). Если вы создаете достаточное количество состояний на сервере для генерации графика, вам нужно будет предоставить некоторые дополнительные параметры вашему контроллеру, чтобы получить правильное изображение, например. src="${g.link(controller: 'myController', action: 'displayGraph', params: ['id': 1234])}"
, где id - это то, как вы извлекаете состояние графика.
Ответ 2
Я считаю, что не о Grails, а о HTML. Вы могли:
- Сделайте выделенное действие, которое передает изображение с изображениями определенных параметров и генерирует изображение в этом действии;
-
Вставьте его base64 в кодировку HTML, например здесь:
< img src= "data: image/gif; base64, R0lGODlhUAAPAKIAAAsL... и т.д." alt= "wow" /" >
Ответ 3
Мое предложение действительно состоит из двух частей.
1) Используйте рекомендуемое решение Rob выше для создания артефакта диаграммы, однако сохраните его в статическом файле с уникальным идентификатором, который будет передан обратно как часть ответа из формы submit, а затем отображение диаграммы не отличается затем рендеринг любого другого изображения.
я бы предположил, что идентификатор должен быть сконструирован из специфицированных параметров, переданных в форме submit, чтобы их можно было использовать в качестве механизма кэширования для рендеринга диаграммы без его восстановления.
2) создайте сервис, возможно Quartz Service, который периодически очищает статические диаграммы, созданные для приложения
Ответ 4
Следующий код работает в 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>
Ответ 5
Просто улучшение ответа @Rob:
Еще один вариант, который немного лучше, вы можете просто визуализировать изображение прямо из действия вашего контроллера:
// 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
Ответ 6
По каким-либо причинам вышеупомянутые решения не отображают никакого изображения. Я использовал:
<img src='${createLink(controller: "myController", action: "displayGraph")}' />
вместо.
Ответ 7
Я использовал FileUploadService для сохранения файла изображения в Grails. Если вы получаете изображения из средств каталога, попробуйте следующее:
<img style="height: 120px;width: 102px;"src="${resource(dir:'personImages', file: personalDetailsInstance.id + '.png')}" />
Ответ 8
Ваш 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()
}
}