Pergunta

Eu quero que meus usuários de aplicativos web para baixar alguns dados como um arquivo Excel.

Eu tenho a seguinte função para enviar um fluxo de entrada no objeto de resposta.

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(); }
            }   
        }
    }

Eu gostaria de transformar o meu objeto HSSFWorkbook para um fluxo de entrada e passá-lo para o 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

Foi útil?

Solução

O problema com a sua pergunta é que você está misturando OutputStreams e InputStreams. Um InputStream é algo que você ler e um OutputStream é algo que você gravar.

Isto é como eu escrever um objeto POI no fluxo de saída.

// 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
  }
}

Se você quiser voltar a usar seu código existente você tem que armazenar os dados POI em algum lugar, em seguida, transformar isso em um fluxo de entrada. Isso seria feito facilmente escrevê-lo a um ByteArrayOutputStream, em seguida, lendo os bytes usando um ByteArrayInputStream, mas eu não recomendo. Seu método existente seria mais útil como uma implementação da tubulação genérico, onde você pode canalizar os dados de um InputStream para e OutputStream, mas você não precisa dele para escrever objetos POI.

Outras dicas

Você pode criar um InputStream de um objeto.

public InputStream generateApplicationsExcel() {
    HSSFWorkbook wb = new HSSFWorkbook();
    // Populate a InputStream from the excel object
    return new ByteArrayInputStream(excelFile.getBytes());
}

Eu acho que entendo o que você está tentando fazer (talvez eu estou undershooting, embora)

você realmente não precisa de tanto código - confira o método de gravação -

HSSFWorkbook wb = new HSSFWorkBook();
//populate

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

Tanto quanto eu me lembro quando eu trabalhava w / POI é isso que eu fiz. Se você está dentro de um framework web você pode ter que finaggle lo para que o quadro não tentar fazer algo com o que ServletOutputStream depois que você fechou. Se ele tenta, você obterá uma exceção jogando dizendo que o fluxo de saída já está fechada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top