0

我正在使用带有表单的 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) 支持,但传递StreamedContentp: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 生命周期或特定范围的内容。或者也许有更简单的方法来实现这个任务?

4

1 回答 1

0

在 Primefaces 中使用 StreamedContentp:graphicImagep:media. 您可以在此处
的 Primefaces 论坛中查看 Cagatay Civici 对此主题的评论。

根据我的经验,当我遇到更棘手(或多或少)的问题时,BalusC 的ThisThis回答帮助了我。

我使用了一个单独的 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);
    }

}

小面代码

<p:media value="/PreviewFile?PREVIEW_FILE_PATH=#{fileManager.previewFilePath}" />

希望这可以帮助。而且stackoverflow本身就有很多关于StreamedContent这个话题的问题,看一遍。

于 2013-09-18T09:04:58.677 回答