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 InputStream escribiremos 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.

Scroll al inicio