Os comento a continuación una forma de detectar la descarga de ficheros desde aplicación.
Este método es compatible con todos los navegadores empleando JQuery 1.x y un par de extensiones del mismo: BlockUI y Cookie. La idea se basa en generar un token de descarga que se escribe en una cookie una vez el fichero ha sido descargado: la aplicación queda a la espera de este token leyendo las cookies cada cierto tiempo.
La implementación es sencilla:
1. Preparar para la descarga de ficheros un iframe vacío en la página index (o la que se emplee como montaje de la aplicación):
"<"iframe src="javascript:''" id="__gwt_downloadFrame" tabIndex='-1'
style="position: absolute; width: 0; height: 0; border: 0"">""<"/iframe">"
2. Llamar a fichero a descargar. Llamamos a un servlet que genera el documento indicando un token que en el fondo es un UID o número aleatorio:
«
String UID = Math.random()*1000*Math.random()*10000;
String url = GWT.getHostPageBaseURL() + «/tools/XXXXXXXX» + «&UID=» + UID;
iniciarProcesoCheckDownload (UID);
DOM.setElementAttribute(RootPanel.get(«__gwt_downloadFrame»).getElement(),»src», url);
«
Donde se invoca una función javascript antes de la descarga para comunicar el token (UID):
«
public static native void iniciarProcesoCheckDownload(String token) /*-{
$wnd.programarEscuchaFichero (token);
}-*/;
«
3. En este proceso estamos llamando a una función de Javascript que realiza el bloqueo de la pantalla y la espera de lectura de cookie, donde hemos incluido un control por tiempo como mecanismo de control. Este código requiere de las librerías JS de JQuery:
«<«script src=»js/jquery-1.10.2.min.js» «>»»<«/script»>»
«<«script src=»js/jquery.cookie.js»>»<«/script»>»
«<«script src=»js/jquery.blockUI.js»»>»»<«/script»>»
«
var fileDownloadCheckTimer;
var downloadToken;
var startTime;
function ocultarDivDescarga() {
$.unblockUI();
window.clearInterval(fileDownloadCheckTimer);
window.status = »;
}
function programarEscuchaFichero(token) {
downloadToken = token;
$.blockUI({baseZ: 3000, message: ‘»<«h1»>»Espere mientras se prepara la descarga … «<«br/»>»»<«br/»>» «<«img src=»custom/LoadingProgressBar.gif» border=»0″ width=»100″/»>» «<«/h1»>»‘ });
startTime = new Date();
fileDownloadCheckTimer = window.setInterval(function () {
var cookieValue = $.cookie(‘FileCookie’);
if (cookieValue == downloadToken) {
ocultarDivDescarga();
}
else {
var endTime = new Date();
var secondsOpen = Math.floor((endTime – startTime) / 1000);
if (secondsOpen> 60*2) { // 2 minutos
// Salimos por tiempo, medida de seguridad
ocultarDivDescarga();
window.alert (‘La descarga no se completó en el tiempo esperado, por favor verifique si ha obtenido el fichero solicitado o inténtelo de nuevo.’);
}
else
{
window.status = ‘Espere mientras se prepara la descarga … (‘+secondsOpen + ‘ segundos )’;
}
}
}, 1000);
}
«
4. En la parte servidora, solo tenemos que recoger el token de la petición:
String token = request.getParameter(«UID»);
5. Y al descargar el fichero incluir una cookie con el token, para que el cliente (navegador web) salga de la espera cuando la lea. Hay que poner la ruta raiz así como un tiempo de expiración no demasiado bajo (problemas con diferencia de hora con servidor, zona horaria, etc.):
// indicar token para control de descarga:
Cookie thecookie = new Cookie(«FileCookie», token);
thecookie.setMaxAge(60 * 60 * 4); // 4 horas de vida TOPS
thecookie.setPath(«/»);
response.addCookie(thecookie);
// Escribir binario en salida
response.setContentType («application/xls»);
response.setHeader («Content-Disposition», «attachment;filename=» + sArchivo);
OutputStream ostSalida = response.getOutputStream();
«[«…»]»
La fuente original de la solución es la siguiente:
http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx