How can I serve binary content from a JSF/Webflow app?

痞子三分冷 提交于 2019-12-04 17:43:09

You want to end up with that image in a <h:graphicImage> component, right? In theory, you could use the data URI format for this.

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

However, you've the problem that it doesn't work across all of the current browsers. MSIE for example limits the length of data URI to 32KB.

If those images are in general larger or you'd like to support outdated browsers as well, then your currently best bet is really to let it point to a fullworthy URL after all.

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

There are two ways to get this to work:

  1. Write the image temporarily to public webcontent and reference it the usual way.

    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!)
    

    And use it as follows:

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

    This however only works if the WAR is expanded and you have write rights to the disk file system. You also need to take cleanup into account. A HttpSessionListener may be helpful in this.

  2. Store the binary data in session and have a HttpServlet to serve it up. Assuming that your bean is request scoped:

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

    and the view look like this:

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

    Create a HttpServlet which is mapped on an url-pattern of /images/* and does like the following in the doGet() method:

    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. 
    
  1. Obtain the response object (in jsf - FacesContext.getCurrentInstance().getExternalContext().getResponse(), and cast to HttpServletResponse) or the OutputStream (JSF 2.0, the last method call above would be getResponseOutputStream())

  2. use the write methods on the response's OutputStream

  3. set the proper Content-Type header

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!