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.

walthersoft sagte
Nice, was looking for something like this. However, it doesn’t compile, where do you get ‘getServletResponse()’ in your download() method from ?
Andreas Höhmann sagte
Its a private method wich return the current HttpServletResponse, i haven’t posted because the code is very easy