如何从HSSFWorkbook对象获取输入流

12

我希望我的Web应用程序用户可以下载某些数据作为Excel文件。

我有以下函数来将一个输入流发送到响应对象中。

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

我想将我的HSSFWorkbook对象转换为输入流,并将其传递给先前的方法。

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

4个回答

10

你的问题在于混淆了OutputStream和InputStream。InputStream是读取数据的工具,而OutputStream是写入数据的工具。

以下是我如何将POI对象写入输出流的方法。

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

如果您想要重复使用现有代码,则需要将POI数据存储在某个地方,然后将其转换为输入流。这可以通过将其写入ByteArrayOutputStream,然后使用ByteArrayInputStream读取这些字节来轻松完成,但我不建议这样做。您现有的方法更适用于通用Pipe实现,在此您可以将数据从InputStream传输到OutputStream,但您不需要它来编写POI对象。


例如:+1。但是我该如何获取HSSFWorkbook的文件大小?我想添加一个名为“Content-Length”的头部。 - WelcomeTo
@MyTitle 我认为如果你想设置一个 content-length 头部,你需要先将流写入 ByteArrayOutputStream 中,然后获取其长度,最后将其写入 HTTP 响应中。 - Mr. Shiny and New 安宇

2
您可以从对象创建一个输入流。
public InputStream generateApplicationsExcel() {
    HSSFWorkbook wb = new HSSFWorkbook();
    // Populate a InputStream from the excel object
    return new ByteArrayInputStream(excelFile.getBytes());
}

2

我的解决方案是先将 HSSFWorkbook 转换为 ByteArrayOutputStream,然后再从 ByteArrayOutputStream 创建一个 InputStream:

        HSSFWorkbook wb = ...

        // Fill an empty output stream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        wb.write(baos);

        // Close the document
        wb.close();

        // Create the input stream (do not forget to close the inputStream after use)
        InputStream is = new ByteArrayInputStream(baos.toByteArray());

0

我想我明白你想做什么(也许我理解不足)

你实际上不需要太多代码 - 看看 write 方法 -

HSSFWorkbook wb = new HSSFWorkBook();
//populate

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

就我记得当我使用POI时,那就是我所做的。如果你在一个Web框架内部,你可能需要调整它,以便框架在你关闭它之后不会尝试对ServletOutputStream进行任何操作。如果它尝试这样做,你将会收到一个异常抛出,告诉你输出流已经关闭了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接