我正在使用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应该是会话或应用程序作用域(因为方法称为乘法次数)。所以我只为此目的制作了第二个应用程序范围的bean(ImageBean
)。
<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()
这是奇怪的事情。在imageBean.getImage()
方法内部,一切正常 - 字段设置,getter工作正常。但随后页面刷新,imageBean.imageStreamedContent()
内的String
将返回null。
更准确 - 它返回旧值,就好像从未调用过setter或在另一个bean实例上调用了setter。我在另一个ImageBean
字段上检查了它:在{{1}}构造函数中初始化它,在处理程序调用的setter中使用另一个值并刷新主窗体的一部分。同样的事情:来自构造函数的旧值。
我认为,我缺少关于bean生命周期或范围特定的东西。或者可能没有那么复杂的方法来实现这个任务?
答案 0 :(得分:0)
在Primefaces中为p:graphicImage
和p:media
使用StreamedContent时出现问题。
您可以在Primefaces论坛here中看到Cagatay Civici对此主题的评论。
根据我的经验,当我让BalusC的问题This和This得到更轻松(或多或少)时帮助了我。
我使用了一个saperate Servlet而不是Managedbean来将动态内容流式传输到p:media
(在我的案例中)。
以下是我的代码供您参考(如果您需要):
<强> PreviewFileServlet.java 强>
@WebServlet("/PreviewFile")
public class PreviewFileServlet extends HttpServlet {
public PreviewFileServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = request.getServletContext();
String path = request.getParameter("PREVIEW_FILE_PATH");
logger.info("Received pathe for Preview:"+path);
try{
if(null!=path){
java.io.File f = new java.io.File(path);
if(f.exists()){
FileInputStream fin = new FileInputStream(f);
byte b[] = new byte[(int)f.length()];
fin.read(b);
response.setContentLength(b.length);
response.setContentType(context.getMimeType(path));
response.getOutputStream().write(b);
response.getOutputStream().close();
logger.info("File sent successfully for Preview.");
}
else{
logger.warn("File sepecified by path:-"+path+"-:, NOT found");
}
}
}catch(Exception e){
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Facelet代码
<p:media value="/PreviewFile?PREVIEW_FILE_PATH=#{fileManager.previewFilePath}" />
希望这会有所帮助。 在stackoverflow本身中有很多关于StreamedContent这个主题的问题,请经过一次。