Páginas

Mostrando entradas con la etiqueta subir ficheros. Mostrar todas las entradas
Mostrando entradas con la etiqueta subir ficheros. Mostrar todas las entradas

31 de agosto de 2013

descarga de ficheros desde aplicación con GWT


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

29 de enero de 2013

Subida archivos con FileUploadField de GXT

- Configuración FormPanel:

        FormPanel fp = new FormPanel();
        fp.setEncoding(Encoding.MULTIPART);
        fp.setMethod(Method.POST);
        fp.setAction("uploadServlet"); // Path del servlet de subida

- Configuración FileUploadField:

        FileUploadField flupldFld = new FileUploadField();
        flupldFld.setName("file");

- Añadir el FileUploadField al FormPanel:

       fp.add(flupldFld, new FormData("100%"));

- Configuración Button:

      myButton.addSelectionListener(new SelectionListener() {

            @Override
            public void componentSelected(ButtonEvent ce) {
               
                if (display.getFlupldFld().getValue() != null) {
                    fp.submit();
                }
            }
        });

- Añadir listener de respuesta de la subida al FormPanel

      fp.addListener(Events.Submit, new Listener () {

            @Override
            public void handleEvent(final FormEvent be) {

                Log.info("[be.getResultHtml()] = " + be.getResultHtml());
                }
            }
        });

- Creas un servlet y con este código tendrás el archivo (necesitarás la librería de apache commons-fileupload)

      FileItemFactory factory = new DiskFileItemFactory();
      ServletFileUpload upload = new ServletFileUpload(factory);
      List items = (List) upload.parseRequest(request);

- También en el servlet puedes escribir algo en su salida para que lo puedas recibir en el 'be.getResultHtml()' del listener que le pusiste al FormPanel.

      response.getOutputStream().print("Fichero subido correctamente");