34

我在 JBoss 7.1.1 上使用 PrimeFaces 3.2。

我正在尝试显示存储在 MySQL 数据库中的 BLOB 中的图像<ui:repeat>。图像存储在a中byte[],然后转换为a StreamedContent,如下所示:

InputStream stream = new ByteArrayInputStream(ingredient.getImage());
ingredient.setJsfImage(new DefaultStreamedContent(stream, "image/jpg"));

然后我试图在 Facelet 中显示它,如下所示:

<ui:repeat var="ingredient" value="#{formBean.ingredientResultSet}">
    <p:panel id="resultsPanel" header="#{ingredient.location.shopName}">
        <p:graphicImage value="#{ingredient.jsfImage}" alt="No picture set" />
...

但是,在加载页面时,我在 JBoss 中收到以下错误:

严重 [org.primefaces.application.PrimeResourceHandler] (http--127.0.0.1-8080-12) 流式动态资源错误。

这是如何引起的,我该如何解决?

4

6 回答 6

57

您需要意识到,<p:graphicImage>实际上只使用一个 URL 呈现一个<img src>元素,然后 Web 浏览器将在解析获得的 HTML 标记并呈现结果时单独调用该 URL。

所以,无论你在它的 getter 方法中做什么,都<p:graphicImage>必须设计成可以在每个请求的基础上调用它。因此,最明智的方法是创建一个<p:graphicImage><f:param>其中<p:graphicImage value>指向一个完全独立的请求或应用程序范围的 bean(因此绝对不是视图或会话范围),并且这些<f:param value>点是唯一的图像标识符。

例如

<p:graphicImage value="#{images.image}">
    <f:param name="id" value="#{someBean.imageId}" />
</p:graphicImage>

支持beanImages看起来像这样:

@Named
@ApplicationScoped
public class Images {

    @EJB
    private ImageService service;

    public StreamedContent getImage() throws IOException {
        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. Return a real StreamedContent with the image bytes.
            String id = context.getExternalContext().getRequestParameterMap().get("id");
            Image image = service.find(Long.valueOf(id));
            return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
        }
    }

}

或者,如果您已经在使用OmniFaces 2.0 或更新版本,那么请考虑使用它<o:graphicImage>来代替它,它可以更直观地使用,几乎完全符合您的预期。另请参阅有关该主题的博客

也可以看看:

于 2012-04-15T12:07:28.580 回答
3

我不明白你为什么需要这个。您可以创建一个 servlet,该 servlet 将使用映射“/images/yourimage.jpg”从数据库中获取图像。

这是一个快速教程,其中包含有关如何执行此操作的相应代码。

JSF - 在 JSF 中显示来自数据库的图像

于 2012-04-17T14:10:03.407 回答
3

谢谢BalusC。我通过在支持 bean 中定义一个整数并在更新图像的 ByteArray 时为其分配一个不同的值来做到这一点。该整数用作图像的唯一标识符。然后我将此整数设置为页面<f:param><p:graphicImage>的值。

图片标签看起来像

 <p:graphicImage value="#{empBean.image}">
    <f:param name="id" value="#{empBean.imageId}" />
  </p:graphicImage>`

并将支持 bean 中的图像设置为

 if(user.getPicture()!=null){
        imageId = (int) new Date().getTime();
        BinaryStreamImpl bs = new BinaryStreamImpl(user.getPicture());  
//picture is byte[] property in user class      
        this.image =   new DefaultStreamedContent(bs.getInputStream(), "image/png");
    }

它现在工作良好。

于 2015-09-02T13:00:49.333 回答
1

您必须记住graphicImage组件在页面上呈现的内容。它呈现给 HTML<img>元素。在浏览器中,将对 JSF 页面进行请求,然后对页面上的每个图像也将发生后续请求。

这些图像来自 PrimeFaces 资源 servlet 而不是 FacesServlet,这意味着托管 Bean 的范围及其属性可能不适用。

尝试先将 blob 加载到字节数组中,然后这可能会开始工作。

编辑:请参阅我对这个类似问题的以下回答。 图形图像未在 Primefaces 中呈现流式内容

于 2012-04-09T15:32:50.567 回答
0
InputStream is = new ByteArrayInputStream((byte[]) yourBlobData);
myImage = new DefaultStreamedContent(is, "image/png");

在jsf页面中;

<p:graphicImage value="#{controller.myImage}" style="width:200px;width:500px" />
于 2014-02-19T09:15:22.890 回答
-2

嗯,我 99% 肯定这<p:graphicImage不适用于 ui:repeat 你会遇到很多问题(因为我做了 XD),我建议你创建一个 servlet 并将图像作为输入流提供(有很多例子出来那里)。

于 2012-04-14T18:22:29.013 回答