2010-04-20 11 views
15

Construyo un libro de POI muy grande en mi servidor web. Mantener todo el libro de trabajo en la memoria, no se escalará para múltiples solicitudes simultáneas. ¿Hay alguna manera de escribir progresivamente el libro de trabajo a la secuencia de salida del servlet? Eso debería reducir el tiempo de respuesta, así como también hacer que la memoria del proceso sea eficiente.Transmitir un libro de POI al flujo de salida del servlet

Respuesta

3

Desafortunadamente, eso es imposible cuando no hay medios de datos secuenciales. Sugeriría buscar otro formato, p. CSV o XML. Ambos pueden escribirse secuencialmente. Si proviene de un DB, incluso se puede hacer más eficiente ya que un DB decente tiene instalaciones integradas para exportar eficientemente a esos formatos. Solo tiene que transmitir los bytes de uno al otro lado.

0

Si usa JExcel Tiene un código de muestra para leer el código de flujo hacia y desde un servlet. http://jexcelapi.sourceforge.net/resources/faq/

El único inconveniente de esta API parece que solo admite hasta Excel 2003 inclusive.

Uso de POI: ¿No puede crear el archivo y servir los bytes del archivo a la secuencia de salida del servlet?

+0

estoy escribiendo el libro de punto de interés al OutputStream servlet. Lo que ocurre detrás de las escenas, es escribir los bytes en el outputtream. Mi pregunta es, no sé cómo escribirla progresivamente. Tengo que esperar hasta que se haya creado todo el libro de trabajo, y solo entonces escribirlo en E/S. Y toma alrededor de un minuto escribir en E/S. No sé si eso está justificado. –

+0

¿Qué tan grande es su hoja de cálculo? ¿Creas la hoja de cálculo o te la dan? Si te lo dan, ¿lo modificas? ¿Cuánto le toma tanto tiempo escribir en E/S? –

7

Si está a punto de generar Excel 2007 (xslx) entonces se podría adaptar el enfoque de BigGridDemo.java como se describe aquí: http://web.archive.org/web/20110821054135/http://www.realdevelopers.com/blog/code/excel

La solución es dejar que generan una PDI xslx contenedor como una plantilla única y corriente los datos reales de la hoja de cálculo como XML en una secuencia de salida zip. La racionalización de la generación de XML depende de usted.

+0

La URL ha expirado, ¿puedes arreglarla? – rohit

0

¿Has probado con el método de escritura directo a HttpServletResponse.getOutputStream()?

favor, eche un vistazo al siguiente ejemplo:

HSSFWorkbook wb = new HSSFWorkbook(); 
HSSFSheet sheet = wb.createSheet("new sheet"); 
... 
OutputStream out = response.getOutputStream(); 
wb.write(out); 
out.close(); 
+2

-1 Esto no responde la pregunta. El OP declara explícitamente que el problema que está tratando de resolver es cómo evitar crear todo y luego escribirlo todo de una vez. – Ophidian

+0

-1 No se puede transmitir un xlxs.Al igual que el OP mencionado – hellojava

+0

Esto todavía se mantendrá en la memoria hasta que todas las filas se escriban en wb –

2

La situación ha mejorado considerablemente ya que el resto de las respuestas fueron escritos - Streaming es ahora parte de Apache Poi.

Consulte la clase SXSSFWorkbook, y la documentation here. Utiliza una ventana de transmisión sobre la hoja, vaciando filas viejas fuera de la ventana a archivos temporales.

Esto se basa en el enfoque BigGridDemo utilizado en hlg's answer, pero ahora forma parte de la distribución oficial.

Aquí está el ejemplo de la documentación:

public static void main(String[] args) throws Throwable { 
    // keep 100 rows in memory, exceeding rows will be flushed to disk 
    SXSSFWorkbook wb = new SXSSFWorkbook(100); 
    Sheet sh = wb.createSheet(); 
    for(int rownum = 0; rownum < 1000; rownum++){ 
     Row row = sh.createRow(rownum); 
     for(int cellnum = 0; cellnum < 10; cellnum++){ 
      Cell cell = row.createCell(cellnum); 
      String address = new CellReference(cell).formatAsString(); 
      cell.setCellValue(address); 
     } 

    } 

    // Rows with rownum < 900 are flushed and not accessible 
    for(int rownum = 0; rownum < 900; rownum++){ 
     Assert.assertNull(sh.getRow(rownum)); 
    } 

    // ther last 100 rows are still in memory 
    for(int rownum = 900; rownum < 1000; rownum++){ 
     Assert.assertNotNull(sh.getRow(rownum)); 
    } 

    FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx"); 
    wb.write(out); 
    out.close(); 

    // dispose of temporary files backing this workbook on disk 
    wb.dispose(); 
} 
Cuestiones relacionadas