Как использовать p:graphicImage с StreamedContent внутри p:dataTable?
Я хочу динамически загружать изображения из базы данных с помощью таблицы данных PrimeFaces. Код выглядит следующим образом, основанный на теме форума PF:
<p:dataTable id="tablaInventario" var="inv" value="#{registrarPedidoController.inventarioList}" paginator="true" rows="10"
selection="#{registrarPedidoController.inventarioSelected}" selectionMode="single"
update="tablaInventario tablaDetalle total totalDesc" dblClickSelect="false" paginatorPosition="bottom">
<p:column sortBy="producto.codigo" filterBy="producto.codigo">
<f:facet name="header">#{msg.codigo}</f:facet>
#{inv.producto.codProducto}
</p:column>
<p:column>
<f:facet name="header">Foto</f:facet>
<p:graphicImage id="photo" value="#{registrarPedidoController.streamedImageById}" cache="FALSE">
<f:param name="inv" value="#{inv.id}" />
</p:graphicImage>
</p:column>
</p:dataTable>
с
public StreamedContent getStreamedImageById() {
DefaultStreamedContent image = null;
String get = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("inv");
System.out.println("[Param]: " + get); // This prints null.
Long id = new Long(get);
List<Inventario> listInventarios = controladorRegistrarPedido.listInventarios();
for (Inventario i : listInventarios) {
if (i.getId().compareTo(id) == 0) {
byte[] foto = i.getProducto().getFoto();
image = new DefaultStreamedContent(new ByteArrayInputStream(foto), "image/png");
}
}
return image;
}
Однако я не могу заставить его работать. Мой параметр передает "ноль" моему бобу. Как это вызвано и как я могу решить это?
Я использую Netbeans 6.9.1, JSF 2.0 и Primefaces 2.2.RC2.
Я продолжал использовать первое решение BalusC, оно работало нормально, но изображения не отображаются в пользовательском интерфейсе. Исключения вырвет Glassfish:
WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
at com.sun.faces.mgbean.BeanManager$ScopeManager$ViewScopeHandler.isInScope(BeanManager.java:552)
Ну, кажется, я работаю благодаря BalusC. Я использовал RequestScoped, SessionScoped или ApplicationScoped для управления getStreamedImageId. Однако в пользовательском интерфейсе всегда устанавливается изображение по умолчанию (для нулевых случаев), а не так, как ожидалось, изображение, соответствующее каждой строке. Новый код:
public StreamedContent streamedById(Long id) {
DefaultStreamedContent image = null;
System.out.println("[ID inventario]: " + id);
List<Inventario> listInventarios = controladorRegistrarPedido.listInventarios();
for (Inventario i : listInventarios) {
if (i.getId().equals(id)) {
byte[] foto = i.getProducto().getFoto();
if (foto != null) {
System.out.println(" [Foto]: " + foto);
image = new DefaultStreamedContent(new ByteArrayInputStream(foto), "image/png");
break;
}
}
}
if (image == null) {
System.out.println(" [Image null]");
byte[] foto = listInventarios.get(0).getProducto().getFoto();
image = new DefaultStreamedContent(new ByteArrayInputStream(foto), "image/png");
}
System.out.println(" [Foto Streamed]: " + image);
return image;
}
3 ответа
<p:graphicImage>
вызовет метод получения дважды. Первый раз, когда <img>
элемент должен быть представлен в HTML и, следовательно, требует URL в src
приписывать. Если вы просто вернетесь new DefaultStreamedContent()
, тогда он автоматически сгенерирует правильный URL в src
приписывать. Второй раз, когда браузер действительно запрашивает изображение, это тот момент, когда вы должны вернуть реальное изображение.
Итак, метод getter должен выглядеть примерно так:
public StreamedContent getStreamedImageById() {
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. Get ID value from actual request param.
String id = context.getExternalContext().getRequestParameterMap().get("id");
Image image = service.find(Long.valueOf(id));
return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
}
}
Изображения сохраняются в базе данных как байт [], если мы сохраняем их через спящий режим. Я загрузил изображения с <p:fileUpload
... тег, затем я сохраняю изображение вместе с другими значениями данных, используя спящий режим.
На второй странице я отображаю данные всей таблицы (конечно, с изображениями), используя
<p:dataTable var="data" value="#{three.all}" ....
и динамические изображения с использованием
<p:graphicImage alt="image" value="#{three.getImage(data)}" cache="false" >
<f:param id="image_id" name="image_id" value="#{data.number}" />
</p:graphicImage></p:dataTable>
Здесь "три" - это название Backing Bean. В методе getAll()
Я извлекаю данные из таблицы в спящем режиме и тем же способом создаю HashMap<Integer, byte[]>
, HashMap - это переменная экземпляра компонента, а компонент - SessionScoped. Я кладу images
(которые находятся в byte[]
форма) вместе с целым числом image_id.
код:
for (int i=0; i<utlst.size(); i++ ){
images.put(utlst.get(i).getNumber(), utlst.get(i).getImage());}
//utlst is the object retrieved from database. number is user-id.
В представлении getImage.xhtml, <p:graphicImage alt="image" value="#{three.getImage(data)}" cache="false" >
это вызывает метод getImage(data /*I am passing current object of the list which is being iterated by
*/ )
код getImage:
public StreamedContent getImage(Util ut) throws IOException {
//Util is the pojo
String image_id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("image_id");
System.out.println("image_id: " + image_id);
if (image_id == null) {
defaultImage=new DefaultStreamedContent(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/Capture.PNG"), "image/png");
return defaultImage;
}
image= new DefaultStreamedContent(new ByteArrayInputStream(images.get(Integer.valueOf(image_id))), "image/png");
return image;
}
просто держите ваши динамические изображения с идентификаторами в HashMap в сеансе, тогда они будут правильно транслироваться.
Спасибо и привет, Zeeshan
В PrimeFaces 3.2 ошибка все еще присутствует. Я делаю обходной путь с
<p:graphicImage value="#{company.charting}">
<f:param id="a" name="a" value="#{cc.attrs.a}" />
<f:param id="b" name="b" value="#{cc.attrs.b}" />
</p:graphicImage>
а также
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String a= externalContext.getRequestParameterMap().get("a");
String b= externalContext.getRequestParameterMap().get("b");
Но даже при этом боб вызывается 2 раза. Но во втором вызове переменная a + b заполняется;-)
Блин баг