web-dev-qa-db-fra.com

Afficher les images blob de base de données dans <p: graphicImage> à l'intérieur de <ui: repeat>

J'utilise PrimeFaces 3.2 sur JBoss 7.1.1.

J'essaie d'afficher une image qui est stockée dans un BLOB dans une base de données MySQL dans <ui:repeat>. L'image est stockée dans un byte[] puis convertie en une StreamedContent comme suit:

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

Ensuite, j'essaye de l'afficher dans un Facelet comme suit:

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

Cependant, lors du chargement de la page, l'erreur suivante apparaît dans JBoss:

SEVERE [org.primefaces.application.PrimeResourceHandler] (http - 127.0.0.1-8080-12) Erreur lors de la diffusion d'une ressource dynamique.

Comment cela est-il causé et comment puis-je le résoudre?

Vous devez comprendre que le <p:graphicImage> restitue un élément <img src> avec juste une URL, qui est ensuite invoquée individuellement par le navigateur Web lorsqu'il est sur le point d'analyser le balisage HTML obtenu et de présenter les résultats. 

Ainsi, quoi que vous fassiez dans la méthode getter de <p:graphicImage>, elle doit être conçue de manière à pouvoir être invoquée à la demande. Ainsi, la solution la plus rationnelle serait de créer un <p:graphicImage> avec un <f:param> dans lequel le <p:graphicImage value> pointe un bean complet d'application ou une application entièrement autonome et le <f:param value> pointe l'identificateur d'image unique.

Par exemple.

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

Où le haricot de sauvegarde Images peut ressembler à ceci:

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

}

Ou, si vous utilisez déjà OmniFaces 2.0 ou plus récent , envisagez d’utiliser son <o:graphicImage> qui peut être utilisé de manière plus intuitive, presque exactement comme vous le souhaitiez. Voir aussi le blog sur le sujet.

Voir également:

53
BalusC

Merci BalusC. J'ai fait cela en définissant un entier dans le bean de sauvegarde et en lui attribuant une valeur différente lors de la mise à jour de ByteArray pour image. Cet entier sert d'identifiant unique pour l'image. Ensuite, je règle cet entier comme valeur de <f:param> dans <p:graphicImage> à la page.

étiquette d'image ressemble à 

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

et en définissant l'image dans le haricot de support comme 

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

Cela fonctionne bien maintenant.

3
imdzeeshan

Je ne comprends pas pourquoi avez-vous besoin de cela. Vous pouvez simplement créer un servlet qui obtiendra l'image de la base de données avec un mappage "/images/yourimage.jpg". 

Voici un tutoriel rapide avec un code correspondant sur la façon de le faire.

JSF - Affichage d'images de la base de données au format JSF

3
Ilya Sidorovich

Vous devez garder à l'esprit ce que le composant graphicImage rend sur la page. Il rend à l'élément HTML <img>. Dans le navigateur, la demande sera faite pour la page JSF, puis les demandes suivantes apparaîtront également pour chacune des images de la page.

Ces images proviennent du servlet de ressources PrimeFaces et non de FacesServlet, ce qui signifie que la portée du bean géré et ses propriétés ne sont probablement pas applicables.

Essayez de charger le blob dans un tableau d'octets en premier, puis ceci commencera probablement à fonctionner.

EDIT: Voir la réponse suivante à cette question similaire. graphicimage ne rendant pas le contenu streamé dans Primefaces

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

en page jsf;

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