gpt4 book ai didi

database - 使用 p :graphicImage and StreamedContent 显示来自数据库或远程源的动态图像

转载 作者:太空狗 更新时间:2023-10-30 01:37:57 25 4
gpt4 key购买 nike

我正在尝试显示在数据库中保存为 StreamedContent 的图像字节在<p:graphicImage>如下:

<p:graphicImage  value="#{item.imageF}" width="50"  id="grpImage" height="80"/>
private StreamedContent content; // getter and setter

public StreamedContent getImageF() {

if (student.getImage() != null) {
InputStream is = new ByteArrayInputStream(student.getImage());
System.out.println("Byte :"+student.getImage());
content = new DefaultStreamedContent(is, "", student.getStuID());
System.out.println("ddd ------------------------------- " + content);
return content;
}

return content;
}

这将返回一个空白图像。这是怎么引起的,我该如何解决?

标准输出打印以下内容:

INFO: Byte :[B@a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@b0887b
INFO: Byte :[B@a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@1d06a92
INFO: Byte :[B@d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@39a60
INFO: Byte :[B@d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@8c3daa
INFO: Byte :[B@124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@1dbe05b
INFO: Byte :[B@124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@66a266
INFO: Byte :[B@a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@1293976
INFO: Byte :[B@a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@17b7399
INFO: Byte :[B@d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@1e245a5
INFO: Byte :[B@d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@4a7153
INFO: Byte :[B@124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@1561bfd
INFO: Byte :[B@124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent@47a8c2

最佳答案

<p:graphicImage>需要一个特殊的 getter 方法。也就是说,每个生成的图像都会调用两次,每次都在完全不同的 HTTP 请求中。

请求 JSF 页面的 HTML 结果的第一个 HTTP 请求将首次调用 getter 以生成 HTML <img>src 中具有正确的唯一且自动生成的 URL 的元素属性,其中包含有关每当 Web 浏览器将要请求图像时应准确调用哪个 bean 和 getter 的信息。请注意,此时 getter 不需要返回图像的内容。它不会以任何方式使用,因为这不是 HTML 的工作方式(图像在 HTML 输出中不是“内联”的,而是单独请求的)。

一旦网络浏览器检索到作为 HTTP 响应的 HTML 结果,它将解析 HTML 源代码,以便将结果直观地呈现给最终用户。一旦网络浏览器遇到 <img>元素在解析 HTML 源期间,然后它将在其 src 中指定的 URL 上发送一个全新的 HTTP 请求。属性以便下载该图像的内容并将其嵌入到视觉呈现中。这将第二次调用 getter 方法,该方法又应返回实际 图像内容。

您的特殊情况中,PrimeFaces 显然无法识别和调用 getter 以检索实际图像内容,或者 getter 没有返回预期的图像内容。 #{item}的用法变量名称和日志中的大量调用表明您在 <ui:repeat> 中使用它或 <h:dataTable> .最有可能的是,支持 bean 是请求范围的,并且数据模型在图像请求期间没有正确保存,并且 JSF 将无法在正确的迭代轮次中调用 getter。 View 范围的 bean 也不会工作,因为当浏览器实际请求图像时,JSF View 状态无处可用。


要解决此问题,最好的办法是重写 getter 方法,以便它可以在每个请求的基础上调用,其中您将唯一图像标识符作为 <f:param> 传递。而不是依赖一些在后续 HTTP 请求期间可能会“不同步”的支持 bean 属性。为此使用一个单独的应用程序范围的托管 bean 是完全有意义的,它没有任何状态。此外,InputStream只能读取一次,不能读取多次。

换句话说:永远不要声明StreamedContent也没有任何 InputStream甚至 UploadedFile作为 bean 属性;只在无状态的 getter 中创建全新的 @ApplicationScoped bean 当网络浏览器实际请求图像内容时

例如

<p:dataTable value="#{bean.students}" var="student">
<p:column>
<p:graphicImage value="#{studentImages.image}">
<f:param name="studentId" value="#{student.id}" />
</p:graphicImage>
</p:column>
</p:dataTable>

哪里StudentImages支持 bean 可以如下所示:

@Named // Or @ManagedBean
@ApplicationScoped
public class StudentImages {

@EJB
private StudentService 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 studentId = context.getExternalContext().getRequestParameterMap().get("studentId");
Student student = studentService.find(Long.valueOf(studentId));
return new DefaultStreamedContent(new ByteArrayInputStream(student.getImage()));
}
}

}

请注意,这是一个非常特殊的情况,考虑到 <p:graphicImage> 如何在 getter 方法中执行业务逻辑是完全合法的。在幕后工作。在 getter 中调用业务逻辑通常是不受欢迎的,另请参见 Why JSF calls getters multiple times .不要将这种特殊情况用作其他标准(非特殊)情况的借口。另请注意,您不能像这样使用 EL 2.2 传递方法参数的功能 #{studentImages.image(student.id)}因为此参数不会以图像 URL 结尾。因此,您确实需要将它们作为 <f:param> 传递.


如果你碰巧使用OmniFaces 2.0 or newer ,然后考虑使用其 <o:graphicImage> 相反,它可以更直观地使用,应用程序范围的 getter 方法直接委托(delegate)给服务方法并支持 EL 2.2 方法参数。

因此:

<p:dataTable value="#{bean.students}" var="student">
<p:column>
<o:graphicImage value="#{studentImages.getImage(student.id)}" />
</p:column>
</p:dataTable>

@Named // Or @ManagedBean
@ApplicationScoped
public class StudentImages {

@EJB
private StudentService service;

public byte[] getImage(Long studentId) {
return studentService.find(studentId).getImage();
}

}

另见 the blog关于这个问题。

关于database - 使用 p :graphicImage and StreamedContent 显示来自数据库或远程源的动态图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8207325/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com