Andreas Höhmann’s Weblog

Just another WordPress.com weblog

JSF, Ajax and file download

Verfasst von Andreas Höhmann am Montag, 31. März 2008

Today i show you a example which combines Ajax (Richfaces) and a “normal” Download in a JSF application.
The bean for the download-code is here:


public class DownloadBean {

  // actionListener="#{bean.execute}"
  public void execute (ActionEvent event) {
   download();
  }

  // action="#{bean.download}"
  public String download() {
    final FacesContext facesContext = FacesContext.getCurrentInstance();
    // XXX create temp. filecontent ... resultFile
    writeOutContent(getServletResponse(), new File(this.resultFile), "file.xml");
    facesContext.responseComplete();
    // dont use jsf-navigation-rules
    return null;
  }

  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.setContentType("text/xml");
      res.setHeader("Content-disposition", "attachment; filename=" + theFilename);
      fastChannelCopy(Channels.newChannel(new FileInputStream(content)), Channels.newChannel(res.getOutputStream()));
    } catch (final IOException e) {
    }
  }

  void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
    final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
    while (src.read(buffer) != -1) {
      buffer.flip();
      dest.write(buffer);
      buffer.compact();
    }
    buffer.flip();
    while (buffer.hasRemaining()){
      dest.write(buffer);
    }
  }
}

Now the facelets snipplets: Not Working – Javascript Error :-(


<h:form>
 <h:commandLink actionListener="#{command.execute}" value="Download"/>
 <h:commandLink action="#{command.download}" value="Download"/>
</h:form> 

Not Working – Download is shown in the current page – the ajax page will replaced with the download-content :-(


<a4j:form>
 <a4j:commandLink actionListener="#{command.execute}" value="Download"/>
 <a4j:commandLink action="#{command.download}" value="Download"/>
</a4j:form>

Working :-)


<a4j:form>
 <a4j:htmlCommandLink actionListener="#{command.execute}" value="Download"/>
 <a4j:htmlCommandLink action="#{command.download}" value="Download"/>
</a4j:form>

<h:form>
 <a4j:htmlCommandLink actionListener="#{command.execute}" value="Download"/>
 <a4j:htmlCommandLink action="#{command.download}" value="Download"/>
</h:form>

The a4j:htmlCommandLink was made for this szenario.

Notice: the fast channel copy routine was introduced by waffel.

2 Antworten zu “JSF, Ajax and file download”

  1. walthersoft sagte

    Nice, was looking for something like this. However, it doesn’t compile, where do you get ‘getServletResponse()’ in your download() method from ?

  2. Its a private method wich return the current HttpServletResponse, i haven’t posted because the code is very easy

Einen Kommentar schreiben

Du musst angemeldet um einen Kommentar abzugeben.