title: File download using RichFaces
body: <p>I got the following to work already:</p>
  
  <ol>
  <li>User can upload a file (i.e. a compressed archive)</li>
  <li>User can uncompress the file on the server</li>
  <li>User can execute some stuff on these files, which results in more files to be generated</li>
  </ol>
  
  <p>Now I need to get step 4 to work:</p>
  
  <ul>
  <li>User can download the files to his own computer again</li>
  </ul>
  
  <p>Can anyone give me a hint? I tried to understand the stuff I found on Google, but it does not work quite as expected. Do I have to set a content type? When I set application/octet stream only txt and csv files would display correctly (in the browser, not as download popup as I wanted) other files would not work...</p>
  
  <p>JSP:</p>
  
  <pre><code>&lt;a4j:commandLink value="Download" action="#{appController.downloadFile}" rendered="#{!file.directory}"&gt;
     &lt;f:param name="file" value="#{file.absoluteFilename}" /&gt;
  &lt;/a4j:commandLink&gt;
  </code></pre>
  
  <p>appController:</p>
  
  <pre><code>public String downloadFile() {
      String filename = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("file");
      File file = new File(filename);
      HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();  
  
      writeOutContent(response, file, file.getName());
  
      FacesContext.getCurrentInstance().responseComplete();
      return null;
  }
  
  private void writeOutContent(final HttpServletResponse res, final File content, final String theFilename) {
      if (content == null) {
          return;
      }
      try {
          res.setHeader("Pragma", "no-cache");
          res.setDateHeader("Expires", 0);
          res.setHeader("Content-disposition", "attachment; filename=" + theFilename);
          FileInputStream fis = new FileInputStream(content);
          ServletOutputStream os = res.getOutputStream();
          int bt = fis.read();
          while (bt != -1) {
              os.write(bt);
              bt = fis.read();
          }
          os.flush();
          fis.close();
          os.close();
      } catch (final IOException ex) {
          Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex);
      }
  }
  </code></pre>