jsf - 在<ui:repeat>裡面的<p:graphicImage>中顯示數據庫blob圖像





primefaces dynamic-content uirepeat (6)


InputStream is = new ByteArrayInputStream((byte[]) yourBlobData);
myImage = new DefaultStreamedContent(is, "image/png");

在jsf頁面;

<p:graphicImage value="#{controller.myImage}" style="width:200px;width:500px" />

我在JBoss 7.1.1上使用PrimeFaces 3.2。

我試圖在<ui:repeat>顯示存儲在MySQL數據庫中的BLOB中的圖像。 圖像存儲在byte[] ,然後轉換為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中收到以下錯誤:

SEVERE [org.primefaces.application.PrimeResourceHandler](http - 127.0.0.1-8080-12)流式動態資源出錯。

這是怎麼造成的,如何解決?




謝謝BalusC。 我通過在backing bean中定義一個整數並在更新圖像的ByteArray時為其分配一個diffent值來做到這一點。 該整數用作圖像的唯一標識符。 然後我在頁面上的<p:graphicImage>將此整數設置為<f:param>值。

圖片標籤看起來像

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

它現在運作良好。




您必須記住graphicImage組件在頁面上呈現的內容。 它呈現給HTML <img>元素。 在瀏覽器中,將為JSF頁面發出請求,然後對頁面上的每個圖像也會發生後續請求。

這些映像來自PrimeFaces資源servlet而不是FacesServlet,這意味著Managed Bean的範圍及其屬性可能不適用。

嘗試首先將blob加載到字節數組中,然後這可能會開始工作。

編輯:請參閱我對此類似問題的以下回答。 graphicimage中沒有渲染streamedcontent的graphicimage




我不明白為什麼你需要這個。 您可以創建一個servlet,它將使用映射“/images/yourimage.jpg”從數據庫中獲取圖像。

這是一個快速教程,其中包含有關如何執行此操作的相應代碼。

JSF - 在JSF中顯示來自數據庫的圖像




你需要意識到<p:graphicImage>實際上只用一個URL呈現一個<img src>元素,然後當它要解析獲得的HTML標記並顯示結果時,webbrowser隨後會單獨調用它。

因此,無論你在<p:graphicImage>的getter方法中做什麼,它的設計必須能夠在每個請求的基礎上調用它。 因此,最理智的方法是使用<f:param>創建<p:graphicImage> ,其中<p:graphicImage value>指向完全獨立的請求或應用程序作用域bean, <f:param value>指向唯一圖像標識符。

例如

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

Images支持bean的位置如下所示:

@ManagedBean
@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> ,它可以更直觀地使用,幾乎可以按照您的預期方式使用。 另請參閱有關該主題的博客

也可以看看:




facet表示容器組件中的命名部分。 例如,您可以為dataTable組件創建頁眉和頁腳構面。 http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_facet.html

當你想要創建使用來自用戶的某些代碼的組件時(例如包裝器),這很有用。

即。 當你想創建隱藏長文本的組件並顯示它的簡短版本時。 你可以只使用元素體,但是你只能得到一個值,如果你想從用戶那裡獲得短版本和長版本,那麼就不能在一個值中做到這一點(不使用某些判別式),只需使用facet和說哪一個是長的,哪個是短版本。

<textShortener>
    <f:facet name="short">
        This text is short.
    </f:facet>
    <f:facet name="long">
        This text is too <b>long</b to be showed when page loads. User have to click the button after the short text to show this.
    </f:facet>
</textShortener>

是的,這可以(而且應該)使用jsf模板完成,但我希望你能得到它。

要問:你在野外xml中定義了facet,沒有人請求它,所以沒有人處理它 - 這就是為什麼它沒有拋出錯誤也沒有顯示任何東西。





jsf primefaces dynamic-content uirepeat graphicimage