Firstly, you can download a file using AJAX, however it will be kept in memory. JavaScript cannot access the users disk for security reasons.
So how do you solve this paradox?
The solution was to create a cookie that was set to true server-side when the file download process was complete. In client-side the cookie is polled every 150ms and when it's set to true it stops showing the progress bar. This solution was provided by BalusC in here.
Step 1 - Create progress bar:
<p:dialog widgetVar="progressLoader" id="divProgress" modal="true" draggable="false" resizable="false" showHeader="false">
<p:graphicImage library="img" name="ajax-loader.gif"/>
</p:dialog>
<p:graphicImage library="img" name="ajax-loader.gif"/>
</p:dialog>
Step 2 - Create functions that show and hide the progress bar in JavaScript:
function showProgress() {
PF('progressLoader').show();
}
function closeLoader() {
PF('progressLoader').hide();
}
Step 3 - When the download is complete, set a custom cookie to true in JAVA:
// set cookie cookie.file.exporting (you can pick your own name) to true (in order to close progress indicator client-side)
FacesContext.getCurrentInstance().getExternalContext().addResponseCookie("cookie.file.exporting", "true", Collections.emptyMap());
Step 4 - The link to download calls a JS function when clicked:
<h:commandLink id="exportAll" styleClass="image" action="#{controller.export()}"onclick="monitorExporting(showProgress, closeLoader);"> <h:graphicImage styleClass="image" library="img" name="img_icone_exportar.png"/> </h:commandLink>
Step 5 - Create JS function that polls the cookie and shows and hides the progress bar:
function monitorExporting(start, complete) {
if(PrimeFaces.cookiesEnabled()) {
if(start) {
start();
}
window.fileExportingMonitor = setInterval(function() {
var exportingComplete = PrimeFaces.getCookie('cookie.file.exporting');
if(exportingComplete === 'true') {
if(complete) {
complete();
}
clearInterval(window.fileExportingMonitor);
PrimeFaces.setCookie('cookie.file.exporting', null);
}
}, 150);
}
}