Estoy tratando de mostrar la imagen de bytes que se guarda en la base de datos como un StreamedContent en el <p:graphicImage> de la siguiente manera:

<p:graphicImage  value="#{item.imageF}" width="50"  id="grpImage" height="80"/>
private StreamedContent content; //getter and setter

public StreamedContent getImageF() {

    if (student.getImage() != null) {
        InputStream is = new ByteArrayInputStream(student.getImage());
        System.out.println("Byte :"+student.getImage());
        content = new DefaultStreamedContent(is, "", student.getStuID());
        System.out.println("ddd ------------------------------- " + content);
        return content;
    }

    return content;
}

Esto devuelve una imagen en blanco. Cómo es esto causó y cómo puedo solucionarlo?

La salida estándar (stdout) imprime el siguiente:

INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]
INFO: Byte :[[email protected]
INFO: ddd ------------------------------- org.primefaces.model.[email protected]

OriginalEl autor minhltnt | 2011-11-21

4 Comentarios

  1. 88

    La <p:graphicImage> requiere un especial método getter. Es a saber, de ser invocado dos veces por la imagen generada, cada uno de una forma completamente diferente de la solicitud HTTP.

    La primera solicitud HTTP, que ha solicitado a los resultados HTML de una página JSF, invocará a la función de captador por primera vez en el fin de generar el código HTML <img> elemento con el derecho único y auto-URL generada en el src atributo que contiene información acerca de frijol y getter exactamente debe ser invocado cada vez que el navegador está a punto de solicitar a la imagen. Tenga en cuenta que el captador no en este momento no necesita para volver a la imagen del contenido. No iba a ser utilizado de ninguna manera como que no ¿cómo funciona el código HTML (imágenes no son «entre líneas» en la salida de HTML, pero que en cambio se solicita por separado).

    Una vez que el webbrowser recupera el HTML resultado como respuesta HTTP, se va a analizar el código fuente HTML para presentar el resultado visualmente para el usuario final. Una vez que el navegador se encuentra con un <img> elemento durante el análisis del código fuente HTML, a continuación, va a enviar una nueva petición HTTP a la URL especificada en su src atributo para descargar el contenido de la imagen y se incrusta en la presentación visual. De este modo se invoca el método getter para el segundo tiempo, que a su vez debe devolver el real el contenido de la imagen.

    En su caso particular PrimeFaces al parecer era incapaz de identificar e invocar la función de captador con el fin de recuperar el real contenido de la imagen, o el captador de no regresar a la espera que el contenido de la imagen. El uso de #{item} nombre de la variable y la gran cantidad de llamadas en el registro sugiere que usted está usando en un <ui:repeat> o un <h:dataTable>. Más probable es que el respaldo de frijol es un ámbito de petición y el datamodel no se conservan adecuadamente durante la petición de la imagen y JSF no podrá invocar la función de captador durante el derecho de la iteración de la ronda. Una vista ámbito de frijol también no funcionará como el JSF el estado de vista en ningún lugar disponible cuando el navegador en realidad las peticiones de la imagen.


    Para resolver este problema, lo mejor es volver a escribir el método getter, como tal, de modo que pueda ser invocada en una base por solicitud en la cual se pasa la imagen única identificador como un <f:param> en lugar de depender de algún respaldo de frijol propiedades que pueden ir «fuera de sincronización» en posteriores solicitudes HTTP. Sería completamente el sentido usar un ámbito de aplicación bean gestionado por esto que no tiene ningún estado. Por otra parte, un InputStream puede ser leído sólo una vez, no varias veces.

    En otras palabras: nunca declarar StreamedContent ni cualquier InputStream o incluso UploadedFile como un bean de la propiedad; sólo crear de nuevo en el captador de un estado @ApplicationScoped bean cuando el webbrowser en realidad pide el contenido de la imagen.

    E. g.

    <p:dataTable value="#{bean.students}" var="student">
        <p:column>
            <p:graphicImage value="#{studentImages.image}">
                <f:param name="studentId" value="#{student.id}" />
            </p:graphicImage>
        </p:column>
    </p:dataTable>

    Donde el StudentImages backing bean puede tener este aspecto:

    @Named //Or @ManagedBean
    @ApplicationScoped
    public class StudentImages {
    
        @EJB
        private StudentService service;
    
        public StreamedContent getImage() throws IOException {
            FacesContext context = FacesContext.getCurrentInstance();
    
            if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
                //So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
                return new DefaultStreamedContent();
            }
            else {
                //So, browser is requesting the image. Return a real StreamedContent with the image bytes.
                String studentId = context.getExternalContext().getRequestParameterMap().get("studentId");
                Student student = studentService.find(Long.valueOf(studentId));
                return new DefaultStreamedContent(new ByteArrayInputStream(student.getImage()));
            }
        }
    
    }

    Por favor, tenga en cuenta que este es un caso muy especial en la realización de la lógica de negocio en un método getter es completamente de fiar, teniendo en cuenta cómo la <p:graphicImage> obras de debajo de las mantas. La invocación de la lógica de negocio en los captadores es decir, generalmente mal visto, véase también Por qué JSF llamadas que recibimos varias veces. No utilizar este caso como excusa para otros estándar (no especiales) de los casos. Por favor, también tenga en cuenta que usted no puede hacer uso de EL 2.2 función del método de pasar argumentos como para #{studentImages.image(student.id)} dado que este argumento no acabe en la URL de la imagen. Así que usted realmente necesita para pasar de ellos como <f:param>.


    Si quieres pasar a utilizar OmniFaces 2.0 o más reciente, a continuación, considere el uso de su <o:graphicImage> lugar que puede ser utilizado de forma más intuitiva, con un ámbito de aplicación método getter directamente delegando el método de servicio y apoyar EL 2.2 argumentos del método.

    Así:

    <p:dataTable value="#{bean.students}" var="student">
        <p:column>
            <o:graphicImage value="#{studentImages.getImage(student.id)}" />
        </p:column>
    </p:dataTable>

    Con

    @Named //Or @ManagedBean
    @ApplicationScoped
    public class StudentImages {
    
        @EJB
        private StudentService service;
    
        public byte[] getImage(Long studentId) {
            return studentService.find(studentId).getImage();
        }
    
    }

    Ver también el blog sobre el tema.

    BalusC, esto es exactamente lo que estaba buscando, sin embargo yo no podía entender cómo la respuesta debe ser enviado de vuelta al cliente. Eres realmente una leyenda. Muchas gracias. 🙂
    eres bienvenido.
    Es posible el uso de ManageBean con RequestScope. Cómo procesar la imagen dinámica con RequestScope bean?
    Ejb y CDI managed beans son inyectados como proxy. La llamada al método en el servidor proxy instancia básicamente localiza la instancia actual en su ámbito de aplicación y, a continuación, se invoca el método deseado. Usted ver esto fácilmente de nuevo en stacktraces de las excepciones procedentes de esos métodos. Su alcance es, por tanto, no están ligados al ámbito de aplicación del cliente y pueden ser más pequeños.
    considere la posibilidad de mover en antes de que sea demasiado tarde.

    OriginalEl autor BalusC

  2. 5

    Intentar incluyendo un tipo mime. En su publicado ejemplo, que la tiene como «». La imagen en blanco puede ser debido a que no reconoce la secuencia como un archivo de imagen, ya que hizo que el campo de una cadena vacía. Para agregar un tipo mime image/png o jpg o imagen y ver si funciona:

    String mimeType = "image/jpg";
    StreamedContent file = new DefaultStreamedContent(bytes, mimeType, filename);  

    OriginalEl autor rcheuk

  3. 4

    Hay un par de posibilidades aquí (y por favor enviar toda la clase si este no lo es).

    1) no está inicializando la imagen correctamente
    2) el flujo es vacío, por lo que usted está consiguiendo nada

    Estoy asumiendo estudiante.getImage() tiene una firma de byte[] por lo tanto, primero asegúrese de que los datos que realmente está intacta y representa una imagen. En segundo lugar, no está especificando un tipo de contenido que debe ser «image/jpg» o lo que sea que estés usando.

    Aquí un poco de código repetitivo para comprobarlo, estoy utilizando Primefaces 2 para esto.

    /** 'test' package with 'test/test.png' on the path */
    @RequestScoped
    @ManagedBean(name="imageBean")
    public class ImageBean
    {
        private DefaultStreamedContent content;
    
        public StreamedContent getContent()
        {
            if(content == null)
            {
                /* use your database call here */
                BufferedInputStream in = new BufferedInputStream(ImageBean.class.getClassLoader().getResourceAsStream("test/test.png"));
                ByteArrayOutputStream out = new ByteArrayOutputStream();
    
                int val = -1;
                /* this is a simple test method to double check values from the stream */
                try
                {
                    while((val = in.read()) != -1)
                        out.write(val);
                }
                catch(IOException e)
                {
                    e.printStackTrace();
                }
    
                byte[] bytes = out.toByteArray();
                System.out.println("Bytes -> " + bytes.length);
                content = new DefaultStreamedContent(new ByteArrayInputStream(bytes), "image/png", "test.png");
            }
    
            return content;
        }
    }

    y algunos marcado…

    <html 
        xmlns="http://www.w3.org/1999/xhtml" 
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:p="http://primefaces.prime.com.tr/ui"
    >
    
        <h:head>
    
        </h:head>
    
        <h:body>
            <p:graphicImage value="#{imageBean.content}" />
        </h:body>
    </html>

    Si ese código funciona, entonces usted está configurado correctamente. A pesar de que es basura código de las secuencias de (no lo utilice en la producción) debe darle un punto a solucionar. Mi conjetura es que usted puede ser que tenga algo que está sucediendo en su JPA o de otro marco de Base de datos de donde eres byte[] está vacío o es el formato equivocado. Alternativamente, usted sólo podría haber un tipo de contenido problema.

    Por último, me gustaría clonar los datos de los granos, de modo que el estudiante.getImage() solo se puede copiar en una nueva matriz, y luego se usa. De esta manera si usted tiene algo desconocido que pasa (algo más que desplazar el objeto o cambiar el byte[] usted no está jugando con su arroyos.

    Hacer algo como:

    byte[] data = new byte[student.getImage().length]
    for(int i = 0; i < data.length; i++)
      data[i] = student.getImage()[i];

    para que tu bean tiene una copia (o Matrices.copia()–lo que flota su barco). No puedo enfatizar lo suficiente cómo algo tan simple como esto/tipo de contenido es por lo general lo que está mal. Buena suerte con él.

    OriginalEl autor Daniel B. Chapman

  4. 3

    La respuesta de BalusC es (como de costumbre) la correcta.

    Pero tener una cosa (como ya se ha dicho por él) en mente. La última petición que se realiza desde el navegador para obtener la URL de la construcción <img> etiqueta. Esto no se hace en un contexto de jsf’.

    Así que si usted trata, por ejemplo, el acceso a la phaseId (tala de árboles o la razón que sea)

    context.getCurrentPhaseId().getName()

    Esto se traducirá en una NullPointerException y de alguna manera engañosa mensaje de error que se obtiene es:

    org.primefaces.application.resource.StreamedContentHandler () - Error in streaming dynamic resource. Error reading 'image' on type a.b.SomeBean

    Me tomó bastante tiempo para averiguar cuál era el problema.

    OriginalEl autor morecore

Dejar respuesta

Please enter your comment!
Please enter your name here