开发者

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

I have a JSF 1.2/Spring Web flow 2.0.7 app that need to serve binary content (an image). This content is fetched 开发者_如何学Gofrom a web service (along with some other data) as a Base64-encoded string, and ends up in the bean together with the rest of the data. How can I get the image to show on my web page?

Note: No, there is no way to make the web service stream the data directly, or even to get the binary data out of the web service without all the other stuff.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜