我正在使用带有表单的 Primefaces 制作页面,该表单具有 ajax 上传图像并在提交整个表单之前预览它的能力。
为了实现这一点,我在主窗体之外制作了对话框:
<p:dialog id="imageDlg" header="Load Image" modal="true"
widgetVar="imageUploadWidget">
<h:form id="imageForm" enctype="multipart/form-data">
<p:fileUpload mode="advanced" auto="true" sizeLimit="9999999"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
fileUploadListener="#{pageBean.imageUploadHandler}">
</p:fileUpload>
</h:form>
</p:dialog>
在主窗体内有p:graphicImage
显示刚刚上传的图像的组件和显示对话框的按钮。页面由视图范围的 bean ( PageBean
) 支持,但传递StreamedContent
给p:graphicImage
值 bean 应该是会话或应用程序范围的(因为方法称为乘法)。ImageBean
所以我只为此目的制作了第二个应用程序范围的bean( )。
<p:graphicImage value="#{imageBean.imageStreamedContent()}"/>
<p:commandButton value="Choose image" type="button"
onclick="imageUploadWidget.show();"/>
代码ImageBean
:
@ApplicationScoped
@ManagedBean
public class ImagesBean implements Serializable {
private byte[] image;
//getter & setter
public StreamedContent imageStreamedContent() {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(getImage()));
}
}
}
下一部分是fileUploadListener
。想法很简单——设置相应的字段PageBean
(在表单提交时保存)ImageBean
(在部分刷新后显示)并更新部分主表单:
@ManagedBean
@ViewScoped
public class PageBean implements Serializable {
@ManagedProperty(value="#{imageBean}")
ImagesBean imagesBean;
...
public void imageUploadHandler(FileUploadEvent event) {
getImagesBean().setImage(event.getFile().getContents());
RequestContext.getCurrentInstance().update("form:tabPanel1");
}
奇怪的事情来了。内部setImage()
方法一切正常 - 字段已设置,getter 工作正常。但是然后页面刷新,imageBean.getImage()
里面imageBean.imageStreamedContent()
返回null。
更准确——它返回旧值,就好像从未调用过 setter 或在另一个 bean 实例上调用过 setter。我在另一个String
字段上检查了它:在构造函数中对其进行了初始化ImageBean
,在处理程序中使用另一个值调用了 setter 并刷新了主窗体的一部分。同样的事情:来自构造函数的旧值。
我认为,我缺少有关 bean 生命周期或特定范围的内容。或者也许有更简单的方法来实现这个任务?