Отображение изображений blob в папке <p: graphicImage> внутри <ui: repeat>
Я использую PrimeFaces 3.2 на JBoss 7.1.1.
Я пытаюсь отобразить изображение, которое хранится в BLOB в базе данных MySQL в <ui:repeat>
. Изображение сохраняется в byte[]
, а затем преобразуется в StreamedContent
следующим образом:
InputStream stream = new ByteArrayInputStream(ingredient.getImage());
ingredient.setJsfImage(new DefaultStreamedContent(stream, "image/jpg"));
Затем я пытаюсь отобразить его в Facelet следующим образом:
<ui:repeat var="ingredient" value="#{formBean.ingredientResultSet}">
<p:panel id="resultsPanel" header="#{ingredient.location.shopName}">
<p:graphicImage value="#{ingredient.jsfImage}" alt="No picture set" />
...
Однако при загрузке страницы я получаю следующую ошибку в JBoss:
SEVERE [org.primefaces.application.PrimeResourceHandler] (http-127.0.0.1-8080-12) Ошибка в потоковом динамическом ресурсе.
Как это вызвано и как я могу его решить?
Ответы
Ответ 1
Вам нужно понять, что <p:graphicImage>
на самом деле отображает элемент <img src>
только с URL-адресом, который затем затем индивидуально вызывается веб-браузером, когда он собирается проанализировать полученную HTML-разметку и представить результаты.
Итак, что бы вы ни делали в методе getter <p:graphicImage>
, он должен быть спроектирован таким образом, чтобы его можно было вызвать по запросу. Таким образом, самым разумным подходом было бы создать <p:graphicImage>
с <f:param>
, в котором <p:graphicImage value>
указывает полностью автономный запрос или область приложения bean, а <f:param value>
указывает уникальный идентификатор изображения.
например.
<p:graphicImage value="#{images.image}">
<f:param name="id" value="#{someBean.imageId}" />
</p:graphicImage>
Где поддержка Images
bean может выглядеть так:
@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()));
}
}
}
Или, если вы уже используете OmniFaces 2.0 или новее, рассмотрите возможность использования <o:graphicImage>
, который можно использовать более интуитивно, почти по-разному, как вы ожидали. См. Также в блоге по этому вопросу.
См. также:
Ответ 2
Я не понимаю, зачем вам это нужно. Вы можете просто создать сервлет, который получит изображение из базы данных с отображением "/images/yourimage.jpg".
Вот краткое руководство с соответствующим кодом в нем о том, как это сделать.
JSF - отображение изображений из базы данных в JSF
Ответ 3
Спасибо BalusC. Я сделал это, установив целое число в резервную копию bean и присвоив ему значение diffent при обновлении ByteArray для изображения. Это целое число служит уникальным идентификатором изображения. Затем я устанавливаю это целое число как значение <f:param>
внутри <p:graphicImage>
на странице.
тег изображения выглядит как
<p:graphicImage value="#{empBean.image}">
<f:param name="id" value="#{empBean.imageId}" />
</p:graphicImage>`
и установка изображения в фоновом режиме bean как
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");
}
Теперь он работает хорошо.
Ответ 4
Вы должны иметь в виду, что компонент graphicImage
отображается на странице. Он отображает элемент HTML <img>
. В браузере будет сделан запрос для страницы JSF, затем последующие запросы будут также выполняться для каждого из изображений на странице.
Эти изображения поступают из сервлета ресурсов PrimeFaces, а не FacesServlet, что означает, что область управляемого Bean и ее свойства, вероятно, неприменимы.
Попробуйте сначала загрузить blob в массив байтов, и это, вероятно, начнет работать.
EDIT: См. мой следующий ответ на этот похожий вопрос. графическое изображение не рендерит streamedcontent в Primefaces
Ответ 5
InputStream is = new ByteArrayInputStream((byte[]) yourBlobData);
myImage = new DefaultStreamedContent(is, "image/png");
на странице jsf;
<p:graphicImage value="#{controller.myImage}" style="width:200px;width:500px" />
Ответ 6
mmm я 99% уверен, что <p:graphicImage
не работает с ui: повторите, у вас будет много проблем с этим (потому что я сделал XD), я рекомендую вам создать сервлет и служить изображениям в качестве входного потока (там есть много примеров).