An easy way to expose a resource for download
Write a seam component that returns a resource object:
@Name("foo") ... public Resource getFile() { return new Resource() { public Object getContentType() { return "application/pdf"; } public byte[] getContent() throws IOException { // Load data } public String getFileName() { return "file.pdf"; } public Disposition getDisposition() { return Disposition.ATTACHMENT; } }; } ...
Wire it using pages.xml
... <page view-id="/file.pdf.xhtml" action="#{foo.file.render}" ></page> ...
And access it from the browser http://localhost:8080/myApp/file.pdf.jsf.
Here is the code for Resource
import java.io.IOException; import javax.faces.context.FacesContext; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.jboss.seam.Component; public abstract class Resource { public void render() throws IOException { FacesContext facesContext = (FacesContext) Component.getInstance("facesContext"); if (!facesContext.getResponseComplete()) { HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse(); response.setContentType(getContentType().toString()); response.setContentLength(getContentSize()); if (Disposition.ATTACHMENT.equals(getDisposition())) { response.setHeader("Content-disposition", "attachment; filename=" + getFileName()); } ServletOutputStream out = response.getOutputStream(); out.write(getContent()); out.flush(); facesContext.responseComplete(); } } public enum Disposition { INLINE, ATTACHMENT; } public abstract Object getContentType(); public abstract byte[] getContent() throws IOException; public int getContentSize() throws IOException { return getContent().length; } public String getFileName() { return ""; } public Disposition getDisposition() { return Disposition.INLINE; }
}
Note that this doesn't work on portals / portlets
Comments