Puoi utilizzare <p:graphicImage>
per visualizzare le immagini memorizzate in un byte[]
, indipendentemente dal byte[]
sorgente (DB, file system del disco, rete, ecc.). L'esempio più semplice è:
<p:graphicImage value="#{bean.streamedContent}" />
che fa riferimento a un StreamedContent
proprietà.
Ciò ha tuttavia un inconveniente, in particolare se utilizzato in un componente iterativo come una tabella di dati:il metodo getter verrà invocato due volte; la prima volta da parte di JSF stesso per generare l'URL per <img src>
e la seconda volta dal browser web quando deve scaricare il contenuto dell'immagine in base all'URL in <img src>
. Per essere efficiente, non dovresti colpire il DB nella prima chiamata getter. Inoltre, per parametrizzare la chiamata al metodo getter in modo da poter utilizzare un metodo generico in cui si passa un ID immagine specifico, è necessario utilizzare un <f:param>
(si noti che la funzione EL 2.2 di passare gli argomenti del metodo non funzionerà affatto poiché non finisce nell'URL di <img src>
!).
Riassumendo, questo dovrebbe fare:
<p:dataTable value="#{bean.items}" var="item">
<p:column>
<p:graphicImage value="#{imageStreamer.image}">
<f:param name="id" value="#{item.imageId}" />
</p:graphicImage>
</p:column>
</p:dataTable>
Il #{item.imageId}
ovviamente restituisce l'identificatore univoco dell'immagine nel DB (la chiave primaria) e quindi non il byte[]
contenuto. Il #{imageStreamer}
è un bean con ambito applicativo che assomiglia a questo:
@ManagedBean
@ApplicationScoped
public class ImageStreamer {
@EJB
private ImageService service;
public StreamedContent getImage() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. 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 imageId = context.getExternalContext().getRequestParameterMap().get("imageId");
Image image = imageService.find(Long.valueOf(imageId));
return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
}
}
}
L'Image
class è in questo particolare esempio solo un @Entity
con un @Lob
su bytes
proprietà (dato che stai usando JSF, ovviamente presumo che tu stia usando JPA per interagire con il DB).
@Entity
public class Image {
@Id
@GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
private Long id;
@Lob
private byte[] bytes;
// ...
}
Il ImageService
è solo un @Stateless
standard EJB, niente di speciale da vedere qui:
@Stateless
public class ImageService {
@PersistenceContext
private EntityManager em;
public Image find(Long id) {
return em.find(Image.class, id);
}
}