Можете да използвате <p:graphicImage>
за показване на изображения, съхранени в byte[]
, независимо от byte[]
източник (DB, дискова файлова система, мрежа и т.н.). Най-простият пример е:
<p:graphicImage value="#{bean.streamedContent}" />
което препраща към StreamedContent
собственост.
Това обаче има клопка, особено когато се използва в итериращ компонент, като например таблица с данни:методът за получаване ще бъде извикан два пъти; първия път от самия JSF да генерира URL за <img src>
и втория път от уеб браузър, когато трябва да изтегли съдържанието на изображението въз основа на URL адреса в <img src>
. За да бъдете ефективни, не трябва да удряте DB при първото извикване на getter. Също така, за да параметризирате извикването на метода за получаване, така че да можете да използвате общ метод, при който предавате специфичен идентификатор на изображение, трябва да използвате <f:param>
(моля, имайте предвид, че функцията EL 2.2 за предаване на аргументи на метода изобщо няма да работи, тъй като това не се озовава в URL на <img src>
!).
Обобщено, това трябва да направи:
<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>
#{item.imageId}
очевидно връща уникалния идентификатор на изображението в DB (първичния ключ) и по този начин не byte[]
съдържание. #{imageStreamer}
е боб с обхват на приложение, който изглежда така:
@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()));
}
}
}
Image
класът в този конкретен пример е просто @Entity
с @Lob
на bytes
свойство (тъй като използвате JSF, аз разбира се предполагам, че използвате JPA за взаимодействие с DB).
@Entity
public class Image {
@Id
@GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
private Long id;
@Lob
private byte[] bytes;
// ...
}
ImageService
е просто стандартен @Stateless
EJB, нищо особено за виждане тук:
@Stateless
public class ImageService {
@PersistenceContext
private EntityManager em;
public Image find(Long id) {
return em.find(Image.class, id);
}
}