2010-12-21 11 views
12

Soy muy nuevo en Grails, por lo que probablemente haya una respuesta muy simple a esta pregunta. Intento mostrar una imagen creada dinámicamente en un gsp. La imagen NO se almacena en una base de datos, se crea sobre la marcha en el controlador.Grails: visualización de la imagen creada en gsp

Lo que esencialmente tengo es un gsp que tiene un formulario que toma un conjunto de entradas de usuario (requestGraph.gsp). Al enviar el formulario, los parámetros se envían a la acción displayGraph en el controlador que consulta información de una base de datos completamente fuera de Grails y crea un gráfico utilizando la biblioteca JFreeChart. Me gustaría mostrar esta imagen dentro de displayGraph.gsp o algo así.

Así que, básicamente dentro requestGraph.gsp tengo un fragmento similar a:

<g:form action="displayGraph"> 
    <!-- ... bunch of labels and boxes --> 
    <g:submitButton name="displayGraph" value="Display Graph" /> 
</g:form> 

dentro del controlador Tengo algo como:

def requestGraph = {} 

def displayGraph = { 
    //... code that uses params to make an image byte array and assigns to var img 
    return [image : img] 
} 

Dentro displayGraph.gsp:

<body> 
    <h1>Graph Title</h1> 
    <!-- ??? How to dislpay image? --> 
</body> 

Intenté canalizar la imagen directamente a la secuencia de salida en la acción DisplayGraph. Esto funciona, pero luego pierdo el control de todos los formatos de página en displayGraph.gsp.

La mayoría de los tutoriales que he encontrado crean una acción dedicada para canalizar la imagen a una salida de vapor y luego llaman esa acción usando una etiqueta. El problema es que mi imagen no está almacenada en una base de datos y no veo forma de pasar la matriz de bytes de la imagen (o incluso los parámetros del formulario) para crear/renderizar la imagen. ¿Puede alguien ayudarme con esto? Gracias.

Respuesta

10

Si escribe los bytes en la secuencia de salida, puede tratar el controlador/acción como la fuente de la imagen en su GSP. He aquí un rápido ejemplo no probado:

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

A continuación, puede acceder a su imagen en el src de una etiqueta <img> así:

<img src="${createLink(controller: 'myController', action: 'displayGraph')}"/> 

actualización:

Después de leer su pregunta de nuevo , esto puede funcionar o no, parece que podría estar mostrando el gráfico como resultado del envío de un formulario. Esto solo funcionará si está almacenando el estado en el servidor en alguna parte (en lugar de solo obtenerlo de la única solicitud donde se envía el formulario). Si almacena suficiente estado en el servidor para generar el gráfico, entonces deberá proporcionar algunos parámetros adicionales a su controlador para obtener la imagen correcta, p. src="${g.link(controller: 'myController', action: 'displayGraph', params: ['id': 1234])}", donde id es la forma de recuperar el estado del gráfico.

+0

Lo he intentado. Me parece que cuando escribo la imagen directamente en la secuencia de salida, se muestra inmediatamente en el navegador como una imagen en lugar de una página web. Esto, por supuesto, significa que no puedo agregar ningún tipo de formato o lógica a la página. – Klam

+0

Eso es lo que sucede si vas directamente a 'myController/displayGraph' en tu navegador; pero si usa eso como 'src' de una imagen, aún tiene control de página. Sin embargo, acabo de actualizar mi respuesta con una estipulación que aún puede impedirte. –

+0

Esta es la forma correcta de hacerlo. Pero te aconsejo que guardes las imágenes y otros archivos en el sistema de archivos y que almacenes en db only path and type. PD Si quiere código para cambiar el tamaño de la imagen (esto fue útil en mi proyecto), pregúnteme. – Stan

2

Creo que no se trata de Grails sino de HTML. Usted podría:

  1. Realice la acción específica que la imagen de las tuberías acepta ciertos parámetros y genere la imagen en esa acción;
  2. incrustarla codificado en base 64 en HTML, como here:

    < img src = "data: image/gif; base64, R0lGODlhUAAPAKIAAAsL ... etc ..." alt = "sorpresa" />

+0

Esta es probablemente la respuesta más elegante, ya que la mayoría de los navegadores lo admiten hoy en día. Sin embargo, si tiene que soportar IE7, esto no funcionará. –

2

mi sugerencia en realidad tiene dos partes.

1) Use la solución recomendar por Rob anteriormente para generar el artefacto gráfico, sin embargo guardarlo en un archivo estático con un identificador único que se pasa de nuevo como parte de la respuesta de la forma de presentar, a continuación, hacer que el gráfico no es diferente a la representación de cualquier otra imagen.

Yo sugeriría que el identificador se construye a partir de los parametros specifif aprobadas en el formulario de envío para que puedan ser utilizados como un mecanismo de almacenamiento en caché para representar el gráfico de nuevo sin reconstruirlo

2) crear un servicio, tal vez a Quartz Service, que periódicamente limpia los gráficos estáticos que se crearon para la aplicación

0

Por alguna razón, las soluciones anteriores no muestran ninguna imagen. Usé:

<img src='${createLink(controller: "myController", action: "displayGraph")}' /> 

en su lugar.

2

El siguiente código funciona en 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() 
    } 
} 

vistas/home/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> 
0

que utiliza FileUploadService para guardar el archivo de imagen en Grails .Si obtener imágenes de los medios de directorio Intente esto:

<img style="height: 120px;width: 102px;"src="${resource(dir:'personImages', file: personalDetailsInstance.id + '.png')}" /> 
2

Sólo una mejora a @ respuesta de Rob:

Otra opción, que es un poco más agradable, sólo puede representar la imagen, directamente de la acción del controlador:

// controller action 
def displayGraph = { 
    def img // a byte[], File or InputStream 
    render(file: img, contentType: 'image/png') 
} 

Ver también: http://grails.org/doc/latest/ref/Controllers/render.html

0

su gsp:

<img src="${createLink(controller: "image", action: "draw")}" /> 

su controlador:

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