2010-05-12 17 views
9

Tengo una página GWT donde el usuario ingresa datos (fecha de inicio, fecha de finalización, etc.), luego estos datos van al servidor a través de una llamada RPC. En el servidor, quiero generar informes de Excel con POI y permitir que el usuario guarde ese archivo en su máquina local.Descargar archivo dinámico con GWT

Este es mi código de prueba para transmitir archivos de vuelta al cliente, pero por alguna razón creo que no sabe cómo se debe transmitir archivo al cliente cuando estoy usando RPC:

public class ReportsServiceImpl extends RemoteServiceServlet implements ReportsService { 
    public String myMethod(String s) { 

     File f = new File("/excelTestFile.xls"); 

     String filename = f.getName(); 

     int length = 0; 

     try { 
      HttpServletResponse resp = getThreadLocalResponse(); 
      ServletOutputStream op = resp.getOutputStream(); 
      ServletContext context = getServletConfig().getServletContext(); 
      resp.setContentType("application/octet-stream"); 
      resp.setContentLength((int) f.length()); 
      resp.setHeader("Content-Disposition", "attachment; filename*=\"utf-8''" + filename + ""); 

      byte[] bbuf = new byte[1024]; 
      DataInputStream in = new DataInputStream(new FileInputStream(f)); 

      while ((in != null) && ((length = in.read(bbuf)) != -1)) { 
       op.write(bbuf, 0, length); 
      } 

      in.close(); 
      op.flush(); 
      op.close(); 

     } 
     catch (Exception ex) { 
      ex.printStackTrace(); 
     } 

     return "Server says: " + filename; 
    } 
} 

tengo leí en algún lado en Internet que no puedes hacer stream de archivos con RPC y tengo que usar Servlet para eso. ¿Hay algún ejemplo de cómo usar Servlet y cómo llamar a ese servlet desde ReportsServiceImpl? ¿Realmente necesito hacer un servlet o es posible volver a transmitirlo con mi RPC?

+0

favor elaborar el problema con más detalle. "no sabe" no es realmente descriptivo. ¿Qué pasa exactamente? ¿Qué pasa exactamente no? – BalusC

+1

La respuesta de @sri tiene sentido. Ahora me toca a mí publicar algunos comentarios: 1) 'DataInputStream' es superfino. Simplemente use 'FileInputStream' directamente. Después de todo * solo * necesita el método 'read()' definido en la clase 'InputStream'. 2) La verificación 'in! = Null' también es superfloosa, ya que ** nunca ** null (creaste una nueva usando' new', que nunca puede ser nula). 3) El encabezado 'Content-Disposition' se ve mal formado en la parte' filename'. Para obtener algunas ideas sobre cómo hacer la entrega del archivo * básico *, puede encontrar útil [este artículo] (http://balusc.blogspot.com/2007/07/fileservlet.html). Buena suerte. – BalusC

Respuesta

14

Tienes que hacer un Servlet regular, no puedes transmitir datos binarios desde ReportsServiceImpl. Además, no hay forma de llamar al servlet desde ReportsServiceImpl: su código de cliente tiene que invocar directamente el servlet.

En el lado del cliente, debe crear un enlace de anclaje normal con los parámetros pasados ​​a través de la cadena de consulta. Algo así como <a href="http://myserver.com/myservlet?parm1=value1&.."</a>.

En el lado del servidor, mueva su código a un Servlet estándar, uno que NO hereda de RemoteServiceServlet. Lea los parámetros del objeto de solicitud, cree el Excel y envíelo al cliente. El navegador abrirá automáticamente el cuadro de diálogo de descarga de archivos.

+1

Sí, esto tiene sentido. ¡Gracias por tu sugerencia! – Maksim

0

Es posible obtener los datos binarios que desea a través del canal RPC de varias maneras ... uuencode, por ejemplo. Sin embargo, aún deberá obtener el navegador para manejar el archivo como una descarga.

Y, en función de su código, parece que está intentando activar el mecanismo estándar del navegador para manejar el tipo mime dado modificando la respuesta en el servidor para que el navegador lo reconozca como una descarga ... abrir un diálogo de guardar, por ejemplo. Para hacer eso, necesita que el navegador haga la solicitud por usted y necesita el servlet allí para manejar la solicitud. Se puede hacer con las URL de reposo, pero al final necesitarás un serviet para hacer eso.

Necesita, en efecto, establecer una URL de ventana del navegador para la URL que devuelve el objeto de respuesta modificado.

Por lo tanto, esta pregunta (sobre transmisión) no es realmente compatible con el ejemplo de código. Se debe ajustar uno u otro (protocolos de comunicación o objeto de respuesta modificado por el servidor).

El más fácil de ajustar es el método de comunicación.

+0

oh lo siento, solo lea la fecha – Rondo

2

puede hacerlo simplemente usando GWT RPC y Data URIs:

  1. En su ejemplo, hacer que su myMethod devolver el archivo de contenido.
  2. En el lado del cliente, formatee un Data URI con el contenido del archivo recibido.
  3. Utilice Window.open para abrir un cuadro de diálogo para guardar el archivo pasando el formato DataURI.

Tome un vistazo a esta referencia, para entender el uso Data URI:

Export to csv in jQuery

+1

Debe tenerse en cuenta que los URI de los datos no son compatibles con IE 6 y 7. Sin embargo, IE8 tiene soporte parcial. – codingscientist