Struts2 + POI: Exportar planilha excel para download no client-side

Boa tarde,

venho tentando montar uma classe que exporte uma planilha excel para o usuario, mas assim que ele clicar no botão,
apareceria aquele dialog para escolher onde salvar o arquivo.

Comecei usando o JExcelAPI, e até consegui gerar o arquivo xls dentro de qualquer pasta, seja no servidor ou na raiz C:.
O problema é que consegui isso fazendo uma classe public static void main, executando local. Quando tentei implementar
isso para funcionar no struts 2, nada funcionou.

Pesquisei muito tempo até que resolvi utilizar outra api, o POI. Consegui grande avanço pois consegui ter um retorno (bem estranho
mas foi um retorno) da minha action. Segue abaixo o meu metodo:

public String exportarExcel(){
		
		HSSFWorkbook workbook = new HSSFWorkbook();
		FileOutputStream file = null;
		
		try{
		     file = new FileOutputStream("poi-test.xls"); 
		}
		catch(IOException e){
		    e.printStackTrace();
		}       
		//Populate workbook with all the excel stuff
		HSSFSheet worksheet = workbook.createSheet("POI Worksheet");
		HSSFRow row = worksheet.createRow(0);
		HSSFCell cell = row.createCell(0);
		cell.setCellValue("Testando");

		//Write to file
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    try{
	        workbook.write(file);
	        workbook.write(baos);
	        ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray()); 
	        excelStream = bis;
	    }
	    catch(IOException e){
	        e.printStackTrace();
	    }
	    return "excel";
		
		/*cf.createExcelFile(listaCursos);
		return "exportarExcel";*/
	}

Aqui vai a configuração do struts.xml:

<action name="curso!*" method="{1}" class="br.com.jm.actions.CursoAction">
	<result name="refreshFormCurso">/incluirCursoForm.jsp</result>
	<result name="refreshAlterarCurso">/detalharCurso.jsp</result>
	<result name="refreshConsultaCurso">/cursos.jsp</result>
	<result name="incluirCurso">/cursos.jsp</result>
	<result name="alterarCurso" type="redirectAction">
		<param name="actionName">curso!consultarCursos</param>
	</result>
	<result name="excluirCurso" type="redirectAction">
		<param name="actionName">curso!consultarCursos</param>
	</result>
	<result name="consultarCursos">/consultaCursos.jsp</result>
	<result name="detalharCurso">/detalharCurso.jsp</result>
	<result name="excel" type="stream">
	        <param name="contentType">application/vnd.ms-excel</param>
	        <param name="inputName">excelStream</param>
	        <param name="contentDisposition">attachment; filename="excelExport.xls"</param>
	        <param name="bufferSize">1024</param>
       </result>
</action>

E aqui vai o screenshot do retorno estranho que recebi…

É possível ver que no meio desse retorno maluco, existe a palavra “Testando”, que configurei no meu metodo para ser
impressa na coluna A1 do arquivo xls…então ainda há esperança! Só me resta que ao invés de vir dentro da minha div um resultado
bem estranho, venha em forma de dialog para o usuario escolher onde deseja salvar o arquivo.

Se for ajudar aqui vai o link que chama essa action:

<s:url id="urlExportarExcel" action="curso!exportarExcel"/>
<sj:a href="%{urlExportarExcel}" button="true" buttonIcon="ui-icon-gear" targets="idDivContent">Exportar para Excel</sj:a>

Ninguém tem a menor idéia?

Acho que o problema não é que seu conteúdo está errado. Mas não está sendo aberto de uma maneira correta. Adiciona ele em uma servlet que deve funcionar.

response.setContentType("text/xls");
response.addHeader("Content-disposition", "attachment; filename=Nome_do_arquivo");
  
ServletOutputStream os = response.getOutputStream();
			
os.write(baos.toByteArray());
os.flush();
os.close();

O meu problema é que como estou trabalhando com struts 2, configurei para que ele interceptasse todas as requisições ao servidor…
desta forma, quando crio um servlet, o struts nao deixa que ele seja executado corretamente.

E se eu nao estiver usando um servlet, não tenho acesso à essas variáveis de response e request. =S

Haveria alguma forma de dizer ao struts para não interceptar 1 chamada em particular?

Não precisa criar Servlet, basta remover o atributo targets da tag sj:a, pois o result “excel” é do tipo stream.