Version 3

    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