wake-up-neo.com

Zeigen Sie Datenbank-Blob-Bilder in <p: graphicImage> in <ui: repeat> an

Ich verwende PrimeFaces 3.2 unter JBoss 7.1.1.

Ich versuche, ein Bild anzuzeigen, das in einem BLOB in einer MySQL-Datenbank in <ui:repeat> gespeichert ist. Das Bild wird in einem byte[] gespeichert und dann wie folgt in eine StreamedContent konvertiert:

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

Dann versuche ich es in einem Facelet wie folgt anzuzeigen:

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

Beim Laden der Seite erhalte ich jedoch folgende Fehlermeldung in JBoss:

SEVERE [org.primefaces.application.PrimeResourceHandler] (http - 127.0.0.1-8080-12) Fehler beim Streaming dynamischer Ressourcen.

Wie wird das verursacht und wie kann ich es lösen?

Sie müssen wissen, dass <p:graphicImage> tatsächlich ein <img src>-Element mit nur einer URL darstellt, die später vom Webbrowser einzeln aufgerufen wird, wenn er das erhaltene HTML-Markup parst und die Ergebnisse präsentiert. 

Was auch immer Sie in der Getter-Methode von <p:graphicImage> tun, muss es so gestaltet sein, dass es auf Anforderungsebene aufgerufen werden kann. Der vernünftigste Ansatz wäre also, einen <p:graphicImage> mit einem <f:param> zu erstellen, wobei der <p:graphicImage value> eine vollständig eigenständige Anforderung oder ein Bean für Anwendungen mit Anwendungsbereich zeigt und der <f:param value> die eindeutige Bild-ID zeigt.

Z.B.

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

Wo die Images Backing Bean so aussehen kann:

@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()));
        }
    }

}

Oder, wenn Sie bereits OmniFaces 2.0 oder neuer verwenden, sollten Sie stattdessen den <o:graphicImage> verwenden, der intuitiver und fast genau so verwendet werden kann, wie Sie es erwartet haben. Siehe auch das Blog zum Thema.

Siehe auch:

53
BalusC

Danke BalusC. Ich habe dieses Ding gemacht, indem ich eine ganze Zahl im Backing-Bean definiert und diesem einen anderen Wert zugewiesen habe, während das ByteArray für image aktualisiert wurde. Diese Ganzzahl dient als eindeutige Kennung für das Bild. Dann setze ich diese Ganzzahl als Wert von <f:param> in <p:graphicImage> auf der Seite.

image-Tag aussehen 

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

und Einstellungsbild in Hintergrundbohne als 

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

Es funktioniert jetzt gut.

3
imdzeeshan

Ich verstehe nicht, warum Sie das brauchen. Sie können einfach ein Servlet erstellen, das das Bild mit einer Zuordnung "/images/yourimage.jpg" aus der Datenbank abruft. 

Hier ist ein kurzes Tutorial mit einem entsprechenden Code dazu.

JSF - Anzeigen von Bildern aus der Datenbank in JSF

3
Ilya Sidorovich

Sie müssen berücksichtigen, was die Komponente graphicImage auf der Seite wiedergibt. Es wird das HTML-Element <img> wiedergegeben. Im Browser wird die Anforderung für die JSF-Seite gestellt. Anschließend werden auch alle Bilder auf der Seite angefordert.

Diese Images stammen vom PrimeFaces-Ressourcenservlet und nicht von FacesServlet. Dies bedeutet, dass der Umfang des Managed Bean und seiner Eigenschaften möglicherweise nicht anwendbar ist.

Laden Sie den Blob zuerst in ein Byte-Array, dann wird dies wahrscheinlich funktionieren.

EDIT: Siehe meine folgende Antwort auf diese ähnliche Frage. Grafikbild wird nicht als Streaming-Inhalt in Primefaces dargestellt

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

in der jsf-Seite;

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