Подтвердить что ты не робот

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.

Большинство учебных пособий, которые я нашел, создают выделенное действие, чтобы передать изображение в выходной поток, а затем вызвать это действие с помощью тега. Проблема в том, что мое изображение не хранится в базе данных, и я не вижу способа передать массив байтов изображения (или даже параметры формы) для создания/рендеринга изображения. Может ли кто-нибудь помочь мне в этом? Спасибо.

4b9b3361

Ответ 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()
  }
}