POIFS

  • Apache POI. Invalid header signature

    Al intentar abrir un fichero con la librería POI de Apache, nos podemos encontrar un con mensaje de error parecido al siguiente:
    [ERROR] Invalid header signature; read 0x3231343130323030, expected 0xE11AB1A1E011CFD0
    java.io.IOException: Invalid header signature; read 0x3231343130323030, expected 0xE11AB1A1E011CFD0
    	at org.apache.poi.poifs.storage.HeaderBlockReader.<init>(HeaderBlockReader.java:107)
    	at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:151)


    Este error está provocado porque el objeto espera un objeto de tipo Stream creado a partir de la lectura de un fichero Excel 2003 o anterior (*.xls;*.xlt). Si visitamos la página POIFS File System Internals, hacia el final de la página, en el apartado File System Structures, podemos encontrar el "por qué" de este error.

  • Como descargar con ajax/jquery un fichero excel generado con Apache POI

    Código para general el fichero excel:

    HSSFWorkbook workbook = new HSSFWorkbook();
    HSSFSheet sheet = workbook.createSheet("Hoja1");
    

    Creamos un fichero temporal (puede ser temporal o no, a tu elección):

    File file = File.createTempFile(dto.getGridName().toLowerCase()+"-", ".xls");

     A partir del fichero creamos un InputStream

    FileOutputStream report = new FileOutputStream( file.getPath() );

    En este InputStreamescribiremos el contenido del fichero excel:

    workbook.write(report);
    //Cerramos el fichero excel
    workbook.close();
    //Cerramos el InputStream
    report.close()

    Para devolver el fichero binario de forma que sea manejable con

    Script utilizaremos el objeto

    Asignamos el content-type:

    response.setContentType("application/vnd.ms-excel;base64");

     Mandamos el encabezado para que el navegador sepa que tiene que descargarse el fichero generado:

    response.setHeader("Content-disposition", "attachment; filename=" + file.getName());

    Leemos el fichero generado con un InputStream

    FileInputStream in = new FileInputStream(file);
    byte[] bytes = new byte[(int)file.length()];
    in.read(bytes);
    
    //Hacemos el encode de los bytes leídos
    String encodedBase64 = new String(Base64.encodeBase64(bytes));
    
    //Escribimos en el objeto response el contenido del mismo
    response.getOutputStream().write(encodedBase64.getBytes());
    
    //Cerramos el InputStream
    in.close();

     

    El código anterior estará en el servidor, ahora se muestra el código JavaScript en la parte Cliente:

     

    			$.ajax({
    				url : url,
    				contentType: "application/vnd.ms-excel",
    				beforeSend : function(xhr) {
    
    					//Aquí podemos mostrar un loader
    				},
    				success : function(data, status, xhr) {
    					
    					//Ocultamos el loader
    					
    					//Si se han devuelto datos
    					if (data != null && data != "FAIL") {
    						var b64Data = data;
    						var contentType = xhr.getResponseHeader("Content-Type"); //Obtenemos el tipo de los datos
    						var filename = xhr.getResponseHeader("Content-disposition");//Obtenemos el nombre del fichero a desgargar
    						filename = filename.substring(filename.lastIndexOf("=") + 1) || "download";
    
    						var sliceSize = 512;
    						
    						
    						var byteCharacters = window.atob(b64Data);
    						var byteArrays = [];
    
    						for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    							var slice = byteCharacters.slice(offset, offset + sliceSize);
    
    							var byteNumbers = new Array(slice.length);
    							for (var i = 0; i < slice.length; i++) {
    								byteNumbers[i] = slice.charCodeAt(i);
    							}
    
    							var byteArray = new Uint8Array(byteNumbers);
    
    							byteArrays.push(byteArray);
    						}
    						//Tras el procesado anterior creamos un objeto blob
    						var blob = new Blob(byteArrays, {
    							type : contentType
    						});
    
    						// IE 10+
    						if (navigator.msSaveBlob) {
    							navigator.msSaveBlob(blob, filename);
    						} else {
    						//Descargamos el fichero obtenido en la petición ajax
    							var url = URL.createObjectURL(blob);
    							var link = document.createElement('a');
    							link.href = url;
    							link.download = filename;
    							document.body.appendChild(link);
    							link.click();
    							document.body.removeChild(link);
    						}
    
    					}
    				},
    				complete : function(xhr, status) {
    					if (xhr.readyState == 4) {
    						if (xhr.status == 200) {
    							//Ocultamos el loader
    
    							var contentLength = xhr.getResponseHeader("Content-Length");
    
    							if (contentLength && contentLength == 0)
    								//Si la descarga está vacía mostramos una alerta
    								alert("No se ha podido descargar el archivo");
    
    						}
    					}
    
    				}
    			});

     

    Con éste código somos capaces de descargar con ajax un fichero binario, generado al vuelo.

Logo M4 ERP
Developer

Seguridad de la página de inicio

Please publish modules in offcanvas position.