Recently I had to use in one of my JSF projects a download link for binary file from server. I didn't want to use my own servlet class, but instead just managed bean. I have done it several times before, but I always forget the proper code :) So here it is, maybe someone will find it useful ;)
public class DownloadManagedBean { /** * This is the action listener method */ public void downloadAction(ActionEvent event) { // Get data from any source you want :) byte [] data = ...; downloadAction("out.bin", data); } /** * This is the core of download action */ protected void downloadAction(String filename, byte[] data) { FacesContext faces = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse) faces.getExternalContext().getResponse(); response.setContentLength(data.length); response.addHeader("Content-Type", "application/x-force-download"); response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); ServletOutputStream out = null; try { long length = data.length; out = response.getOutputStream(); response.setContentLength((int) length); out.write(data, 0, (int) length); } catch (Exception ex) { System.err.println(ex); } finally { if (out != null) { try { out.close(); } catch (Exception ex) { System.err.println(ex); } } } // The most important line - finish response as we have already // close output stream response writer faces.responseComplete(); } }
To use above bean, we just put the following code inside JSF page source:
<h:form> <h:commandlink actionlistener="#{downloadManagedBean.downloadAction}" immediate="true" target="_blank" value="Download"> </h:commandlink> </h:form>
We could change downloadAction method to be more flexible, by using buffered streams and files as data sources, that may be located anywhere in the server's local filesystem. Above example uses for simplicity byte array only to show the main idea how to make it work.
0 comments:
Post a Comment