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:
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.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 anurl-pattern
of/images/*
and does like the following in thedoGet()
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.
Obtain the response object (in jsf -
FacesContext.getCurrentInstance().getExternalContext().getResponse()
, and cast toHttpServletResponse
) orthe OutputStream
(JSF 2.0, the last method call above would begetResponseOutputStream()
)use the
write
methods on the response'sOutputStream
set the proper
Content-Type
header
精彩评论