Bạn có thể sử dụng <p:graphicImage>
để hiển thị hình ảnh được lưu trữ trong một byte[]
, bất kể byte[]
nguồn (DB, hệ thống tệp đĩa, mạng, v.v.). Ví dụ đơn giản nhất là:
<p:graphicImage value="#{bean.streamedContent}" />
trong đó đề cập đến một StreamedContent
tài sản.
Tuy nhiên, điều này có một cạm bẫy, đặc biệt khi được sử dụng trong một thành phần lặp lại chẳng hạn như bảng dữ liệu:phương thức getter sẽ được gọi hai lần; lần đầu tiên do chính JSF tạo URL cho <img src>
và lần thứ hai bằng trình duyệt web khi cần tải xuống nội dung hình ảnh dựa trên URL trong <img src>
. Để hiệu quả, bạn không nên nhấn DB trong lần gọi đầu tiên. Ngoài ra, để tham số hóa lệnh gọi phương thức getter để bạn có thể sử dụng một phương pháp chung trong đó bạn chuyển một ID hình ảnh cụ thể, bạn nên sử dụng <f:param>
(xin lưu ý rằng tính năng EL 2.2 truyền đối số phương thức hoàn toàn không hoạt động vì nó không xuất hiện trong URL của <img src>
!).
Tóm lại, điều này nên làm:
<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}
rõ ràng trả về idenfitier duy nhất của hình ảnh trong DB (khóa chính) và do đó không byte[]
các nội dung. #{imageStreamer}
là một bean phạm vi ứng dụng trông giống như sau:
@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
trong ví dụ cụ thể này chỉ là một @Entity
với một @Lob
trên bytes
thuộc tính (vì bạn đang sử dụng JSF, tôi cho rằng bạn đang sử dụng JPA để tương tác với DB).
@Entity
public class Image {
@Id
@GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
private Long id;
@Lob
private byte[] bytes;
// ...
}
ImageService
chỉ là một @Stateless
tiêu chuẩn EJB, không có gì đặc biệt để xem ở đây:
@Stateless
public class ImageService {
@PersistenceContext
private EntityManager em;
public Image find(Long id) {
return em.find(Image.class, id);
}
}