如何在p:dataTable中使用带有StreamedContent的p:graphicImage?

San*_*ero 11 datatable jsf image primefaces jsf-2

我想使用PrimeFaces数据表从数据库动态加载图像.代码如下所示,基于此PF论坛主题:

<p:dataTable id="tablaInventario" var="inv" value="#{registrarPedidoController.inventarioList}" paginator="true" rows="10"
    selection="#{registrarPedidoController.inventarioSelected}" selectionMode="single"                                     
    update="tablaInventario tablaDetalle total totalDesc" dblClickSelect="false" paginatorPosition="bottom">
    <p:column sortBy="producto.codigo" filterBy="producto.codigo">
        <f:facet name="header">#{msg.codigo}</f:facet>
        #{inv.producto.codProducto}
    </p:column>                            
    <p:column>
        <f:facet name="header">Foto</f:facet>
        <p:graphicImage id="photo" value="#{registrarPedidoController.streamedImageById}" cache="FALSE">
            <f:param name="inv" value="#{inv.id}" />
        </p:graphicImage>                                
    </p:column>
</p:dataTable>
Run Code Online (Sandbox Code Playgroud)

public StreamedContent getStreamedImageById() {
    DefaultStreamedContent image = null;
    String get = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("inv");
    System.out.println("[Param]: " + get); // This prints null.
    Long id = new Long(get);
    List<Inventario> listInventarios = controladorRegistrarPedido.listInventarios();

    for (Inventario i : listInventarios) {
        if (i.getId().compareTo(id) == 0) {
            byte[] foto = i.getProducto().getFoto();
            image = new DefaultStreamedContent(new ByteArrayInputStream(foto), "image/png");
        }
    }

    return image;
}
Run Code Online (Sandbox Code Playgroud)

但是我无法让它发挥作用.我的参数将"null"传递给我的支持bean.这是怎么造成的,我该如何解决?

我使用的是Netbeans 6.9.1,JSF 2.0和Primefaces 2.2.RC2.

我继续使用BalusC第一个解决方案,它工作正常,但图像没有在UI中呈现.例外Glassfish呕吐:

WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
        at com.sun.faces.mgbean.BeanManager$ScopeManager$ViewScopeHandler.isInScope(BeanManager.java:552)
Run Code Online (Sandbox Code Playgroud)

好吧,我感谢BalusC.我将使用RequestScoped,SessionScoped或ApplicationScoped来管理getStreamedImageId.但是,在UI中始终设置默认图像(对于空的情况)而不是预期的与每行对应的图像.新代码是:

public StreamedContent streamedById(Long id) {
    DefaultStreamedContent image = null;

    System.out.println("[ID inventario]: " + id);

    List<Inventario> listInventarios = controladorRegistrarPedido.listInventarios();
    for (Inventario i : listInventarios) {
        if (i.getId().equals(id)) {
            byte[] foto = i.getProducto().getFoto();
            if (foto != null) {
                System.out.println("   [Foto]: " + foto);
                image = new DefaultStreamedContent(new ByteArrayInputStream(foto), "image/png");
                break;
            }
        }


    }
    if (image == null) {
        System.out.println("       [Image null]");
        byte[] foto = listInventarios.get(0).getProducto().getFoto();
        image = new DefaultStreamedContent(new ByteArrayInputStream(foto), "image/png");
    }

    System.out.println("   [Foto Streamed]: " + image);

    return image;

}
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 33

<p:graphicImage>会调用两次getter方法.第一次是将<img>元素呈现为HTML,因此需要在src属性中使用URL .如果您只是返回new DefaultStreamedContent(),那么它将自动生成src属性中的正确URL .第二次是浏览器真正请求图像时,这是您应该返回实际图像的时刻.

所以,getter方法基本上应该是这样的:

public StreamedContent getStreamedImageById() {
    FacesContext context = FacesContext.getCurrentInstance();

    if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
        // So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL.
        return new DefaultStreamedContent();
    }
    else {
        // So, browser is requesting the image. Get ID value from actual request param.
        String id = context.getExternalContext().getRequestParameterMap().get("id");
        Image image = service.find(Long.valueOf(id));
        return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为`p:graphicImage`内容提供服务的bean需要是请求或会话作用域(如果它无论如何都是无状态的应用程序范围).视图范围不受支持.您需要将视图范围bean中的方法拆分为适当范围内的单独Bean.这还有一个额外的好处,即它可以在其他地方更好地重复使用. (4认同)
  • BalusC卓越的答案,质量上乘.我使用第一个解决方案,它正在使用long参数,我从数据库中获取图像,但是没有在UI中呈现,我检查了Glassfish日志并且存在一些例外,任何想法?(我在帖子中添加了.) (3认同)
  • 我首先要分享例外,因为它们通常已经是完整的答案.堆栈跟踪的类型,消息和第1行通常是足够的信息. (2认同)