2008-12-18 15 views
8

Quiero que los usuarios de mi aplicación web descarguen algunos datos como un archivo de Excel.Cómo puedo obtener un flujo de entrada del objeto HSSFWorkbook

Tengo la siguiente función para enviar un flujo de entrada en el objeto de respuesta.

public static void sendFile(InputStream is, HttpServletResponse response) throws IOException { 
     BufferedInputStream in = null; 
     try { 
      int count; 
      byte[] buffer = new byte[BUFFER_SIZE]; 
      in = new BufferedInputStream(is); 
      ServletOutputStream out = response.getOutputStream(); 
      while(-1 != (count = in.read(buffer))) 
       out.write(buffer, 0, count); 
      out.flush();    
     } catch (IOException ioe) { 
      System.err.println("IOException in Download::sendFile"); 
      ioe.printStackTrace(); 
     } finally { 
      if (in != null) { 
       try { in.close(); 
       } catch (IOException ioe) { ioe.printStackTrace(); } 
      } 
     } 
    } 

me gustaría transformar mi objeto HSSFWorkbook a un flujo de entrada y pasarlo al método anterior.

public InputStream generateApplicationsExcel() { 
    HSSFWorkbook wb = new HSSFWorkbook(); 
    // Populate the excel object 
    return null; // TODO. return the wb as InputStream 
} 

http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFWorkbook.html

Respuesta

10

El problema con su pregunta es que está mezclando OutputStreams y InputStreams. Un InputStream es algo de lo que se lee y un OutputStream es algo en lo que se escribe.

Así escribo un objeto POI en la secuencia de salida.

// this part is important to let the browser know what you're sending 
response.setContentType("application/vnd.ms-excel"); 
// the next two lines make the report a downloadable file; 
// leave this out if you want IE to show the file in the browser window 
String fileName = "Blah_Report.xls"; 
response.setHeader("Content-Disposition", "attachment; filename=" + fileName); 

// get the workbook from wherever 
HSSFWorkbook wb = getWorkbook(); 
OutputStream out = response.getOutputStream(); 
try { 
    wb.write(out); 
}  
catch (IOException ioe) { 
    // if this happens there is probably no way to report the error to the user 
    if (!response.isCommited()) { 
    response.setContentType("text/html"); 
    // show response text now 
    } 
} 

Si desea volver a utilizar el código existente que tendría que almacenar los datos de puntos de interés en algún lugar y luego convertir eso en un flujo de entrada. Eso se haría fácilmente escribiéndolo en ByteArrayOutputStream, luego leyendo esos bytes usando ByteArrayInputStream, pero no lo recomendaría. Su método existente sería más útil como una implementación genérica de tuberías, donde puede canalizar los datos de un InputStream a un OutputStream, pero no lo necesita para escribir objetos POI.

+0

+1 por ejemplo. ¿Pero cómo puedo obtener el tamaño de archivo de HSSFWorkbook? Quiero agregar un encabezado 'Content-Length' – MyTitle

+0

@MyTitle. Creo que si quisieras configurar un encabezado de longitud de contenido necesitarías primero escribir la secuencia en un ByteArrayOutputStream, luego obtener su longitud y luego escribirla en el HTTP respuesta. –

0

creo que entiendo lo que estás tratando de hacer (quizás estoy quedarse corto, sin embargo)

que realmente no necesita que gran parte de código - comprobar a cabo el método de escritura -

HSSFWorkbook wb = new HSSFWorkBook(); 
//populate 

ServletOutputStream out = response.getOutputStream(); 
try { 
    wb.write(out); 
    out.flush(); 
}  
catch (IOException ioe) { 
    //whatever 
} 
out.close(); 

Por lo que recuerdo cuando trabajé con POI, eso es lo que hice. Si está dentro de un marco web, es posible que tenga que arreglárselas para que el marco no intente hacer algo con ese ServletOutputStream después de que lo haya cerrado. Si lo intenta, obtendrá una excepción lanzando que le indica que la secuencia de salida ya está cerrada.

Cuestiones relacionadas