【问题标题】:How can I serve binary content from a JSF/Webflow app?如何从 JSF/Webflow 应用程序提供二进制内容?
【发布时间】:2011-05-07 05:55:16
【问题描述】:

我有一个需要提供二进制内容(图像)的 JSF 1.2/Spring Web flow 2.0.7 应用程序。该内容是从 Web 服务(连同一些其他数据)作为 Base64 编码字符串获取的,并与其余数据一起在 bean 中结束。如何让图片显示在我的网页上?

注意:不,没有办法让 Web 服务直接流式传输数据,甚至无法在没有其他任何东西的情况下从 Web 服务中获取二进制数据。

【问题讨论】:

    标签: java jsf streaming spring-webflow


    【解决方案1】:

    您希望在<h:graphicImage> 组件中得到该图像,对吧?理论上,您可以为此使用data URI format

    <h:graphicImage value="data:image/png;base64,#{bean.base64Image}" />
    

    但是,您的问题是它不能在所有当前浏览器上运行。例如,MSIE 将 data URI 的长度限制为 32KB。

    如果这些图像通常更大,或者您也希望支持过时的浏览器,那么您目前最好的选择是让它指向一个完整的 URL毕竟

    <h:graphicImage value="images/filename.png" />
    

    有两种方法可以让它工作:

    1. 将图像临时写入公共网络内容并以通常的方式引用它。

      this.uniqueImageFileName = getOrGenerateItSomehow();
      byte[] imageContent = convertBase64ToByteArraySomehow();
      ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
      ServletContext sc = (ServletContext) ec.getContext();
      File image = new File(sc.getRealPath("/images"), uniqueImageFileName);
      // Write byte[] to FileOutputStream on that file the usual way (and close!)
      

      并按如下方式使用:

      <h:graphicImage value="images/#{bean.uniqueImageFileName}" />
      

      这仅在 WAR 展开并且您对磁盘文件系统具有写入权限时才有效。您还需要考虑清理。 HttpSessionListener 可能对此有所帮助。

    2. 将二进制数据存储在会话中,并有一个HttpServlet 来提供它。假设您的 bean 是请求范围的:

      this.uniqueImageFileName = getOrGenerateItSomehow();
      byte[] imageContent = convertBase64ToByteArraySomehow();
      ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
      ec.getSessionMap().put(uniqueImageFileName, imageContent);
      

      视图如下所示:

      <h:graphicImage value="images/#{bean.uniqueImageFileName}" />
      

      创建一个HttpServlet,它映射到/images/*url-pattern,并在doGet() 方法中执行以下操作:

      String uniqueImageFileName = request.getPathInfo().substring(1);
      byte[] imageContent = (byte[]) request.getSession().getAttribute(uniqueImageFileName);
      response.setContentType("image/png"); // Assuming it's always PNG.
      response.setContentLength(imageContent.length);
      // Write byte[] to response.getOutputStream() the usual way. 
      

    【讨论】:

    • 非常感谢您的回答。最后一部分是我最终要做的,除了包含数据的 bean 在 WebFlows 流范围内,而不是在任何 JSF 范围内。因此,我在流程中调用了一些代码,将 bean 从 SWF 流程范围复制到会话。然后我从 Servlet 中的会话中检索数据。这有点hacky,但我找不到更好的方法。
    【解决方案2】:
    1. 获取响应对象(在 jsf - FacesContext.getCurrentInstance().getExternalContext().getResponse(),并转换为 HttpServletResponse)或 the OutputStream(JSF 2.0,上面的最后一个方法调用将是 getResponseOutputStream()

      李>
    2. 在响应的OutputStream 上使用write 方法

    3. 设置正确的Content-Type标头

    【讨论】:

    • print? writeExternalContext#getResponseOutputStream() 仅适用于 JSF 2.0。
    • 我应该把这段代码放在哪里?我没有 JSF 控制器或任何东西,只有一堆 webflow XML。
    • @mranders - 好吧,你至少需要一些代码 - 否则你首先如何获得图像?
    • 我的服务类中有一些代码,但它只是将 Web 服务对象映射到一个 bean。数据在我的 bean 对象中。你的意思是我应该把代码放在 bean 对象中?
    • 我不知道——“bean”是一个非常广泛的术语。而且我看不到您的应用程序结构:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-27
    • 2016-05-02
    • 1970-01-01
    相关资源
    最近更新 更多