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

时间:2011-11-29 02:06:40

标签: image jsf jsf-2 datatable primefaces

我想使用PrimeFaces数据表从数据库动态加载图像。代码如下所示,基于this PF forum topic

<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>

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;
}

但是我无法让它发挥作用。我的参数将“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)

感谢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;

}

3 个答案:

答案 0 :(得分:33)

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

所以,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()));
    }
}

答案 1 :(得分:3)

如果我们通过休眠保存它们,图像将作为byte []保存在数据库中。我使用<p:fileUpload ...标签上传了图像,然后使用hibernate将图像与其他数据值一起保存。

在第二页上,我正在使用

显示整个表格数据(当然还有图像)
<p:dataTable  var="data" value="#{three.all}" ....

和使用

的动态图像
<p:graphicImage   alt="image"  value="#{three.getImage(data)}" cache="false"  >
                <f:param id="image_id" name="image_id" value="#{data.number}" />
</p:graphicImage></p:dataTable>

这里“三”是Backing Bean的名称。在方法getAll()中,我正在通过hibernate从表中检索数据,并且在同一方法中,我创建了一个HashMap<Integer, byte[]>。 HashMap是bean的实例变量,Bean是SessionScoped。我将images(以byte[]形式)与整数image_id放在一起。

代码:

    for (int i=0; i<utlst.size(); i++ ){
             images.put(utlst.get(i).getNumber(), utlst.get(i).getImage());}
//utlst is the object retrieved from database. number is user-id.

在视图getImage.xhtml中,<p:graphicImage alt="image" value="#{three.getImage(data)}" cache="false" >调用方法getImage(data /*I am passing current object of the list which is being iterated by */ )

getImage的代码:

public StreamedContent getImage(Util ut) throws IOException {
       //Util is the pojo

          String image_id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("image_id");
          System.out.println("image_id: " + image_id);

          if (image_id == null) {

                defaultImage=new DefaultStreamedContent(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/Capture.PNG"), "image/png");

            return defaultImage; 
        }


         image= new DefaultStreamedContent(new ByteArrayInputStream(images.get(Integer.valueOf(image_id))), "image/png");

        return image;
    }

只需在会话中使用A HashMap中的ID保存动态图像,然后就可以正确地对其进行流式处理。

谢谢&amp;问候, Zeeshan

答案 2 :(得分:2)

在PrimeFaces 3.2中,错误仍然存​​在。我用

做了解决方法
<p:graphicImage value="#{company.charting}">
    <f:param id="a" name="a" value="#{cc.attrs.a}" />
    <f:param id="b" name="b" value="#{cc.attrs.b}" />
</p:graphicImage>

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String a= externalContext.getRequestParameterMap().get("a");
String b= externalContext.getRequestParameterMap().get("b");

但即便如此,豆子被召唤2次。但是在第二个调用变量a + b被填充; - )

该死的bug