如何从HSSFWorkbook对象获取输入流

时间:2021-02-27 20:22:54

I want my web application users to download some data as an Excel file.

我希望我的Web应用程序用户将一些数据下载为Excel文件。

I have the next function to send an Input Stream in the response object.

我有下一个函数在响应对象中发送输入流。

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

I would like to transform my HSSFWorkbook Object to an input stream and pass it to the previous method.

我想将我的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

3 个解决方案

#1


The problem with your question is that you are mixing OutputStreams and InputStreams. An InputStream is something you read from and an OutputStream is something you write to.

您的问题的问题是您正在混合OutputStreams和InputStreams。 InputStream是您读取的内容,OutputStream是您编写的内容。

This is how I write a POI object to the output stream.

这就是我如何将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
  }
}

If you wanted to re-use your existing code you'd have to store the POI data somewhere then turn THAT into an input stream. That'd be easily done by writing it to a ByteArrayOutputStream, then reading those bytes using a ByteArrayInputStream, but I wouldn't recommend it. Your existing method would be more useful as a generic Pipe implementation, where you can pipe the data from an InputStream to and OutputStream, but you don't need it for writing POI objects.

如果您想重新使用现有代码,则必须将POI数据存储在某处,然后将其转换为输入流。这可以通过将其写入ByteArrayOutputStream,然后使用ByteArrayInputStream读取这些字节来轻松完成,但我不推荐它。您现有的方法作为通用管道实现会更有用,您可以将数据从InputStream传递到OutputStream,但是您不需要它来编写POI对象。

#2


you can create a InputStream from a object.

您可以从对象创建一个InputStream。

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

#3


I think I understand what you're trying to do (maybe I am undershooting, though)

我想我明白你要做的事情(也许我正在低估)

you don't really need that much code - check out the write method -

你真的不需要那么多代码 - 看看写方法 -

HSSFWorkbook wb = new HSSFWorkBook();
//populate

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

As far as I remember when I worked w/ POI that's what I did. If you're inside a web framework you may have to finaggle it so that the framework doesn't try to do something with the that ServletOutputStream after you've closed it. If it tries, you'll get an exception throwing telling you that the output stream is closed already.

据我所知,当我与POI一起工作时,这就是我所做的。如果你在一个Web框架内,你可能需要对其进行处理,以便框架在关闭它之后不会尝试对该ServletOutputStream执行某些操作。如果它尝试,你会得到一个异常抛出告诉你输出流已经关闭。

#1


The problem with your question is that you are mixing OutputStreams and InputStreams. An InputStream is something you read from and an OutputStream is something you write to.

您的问题的问题是您正在混合OutputStreams和InputStreams。 InputStream是您读取的内容,OutputStream是您编写的内容。

This is how I write a POI object to the output stream.

这就是我如何将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
  }
}

If you wanted to re-use your existing code you'd have to store the POI data somewhere then turn THAT into an input stream. That'd be easily done by writing it to a ByteArrayOutputStream, then reading those bytes using a ByteArrayInputStream, but I wouldn't recommend it. Your existing method would be more useful as a generic Pipe implementation, where you can pipe the data from an InputStream to and OutputStream, but you don't need it for writing POI objects.

如果您想重新使用现有代码,则必须将POI数据存储在某处,然后将其转换为输入流。这可以通过将其写入ByteArrayOutputStream,然后使用ByteArrayInputStream读取这些字节来轻松完成,但我不推荐它。您现有的方法作为通用管道实现会更有用,您可以将数据从InputStream传递到OutputStream,但是您不需要它来编写POI对象。

#2


you can create a InputStream from a object.

您可以从对象创建一个InputStream。

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

#3


I think I understand what you're trying to do (maybe I am undershooting, though)

我想我明白你要做的事情(也许我正在低估)

you don't really need that much code - check out the write method -

你真的不需要那么多代码 - 看看写方法 -

HSSFWorkbook wb = new HSSFWorkBook();
//populate

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

As far as I remember when I worked w/ POI that's what I did. If you're inside a web framework you may have to finaggle it so that the framework doesn't try to do something with the that ServletOutputStream after you've closed it. If it tries, you'll get an exception throwing telling you that the output stream is closed already.

据我所知,当我与POI一起工作时,这就是我所做的。如果你在一个Web框架内,你可能需要对其进行处理,以便框架在关闭它之后不会尝试对该ServletOutputStream执行某些操作。如果它尝试,你会得到一个异常抛出告诉你输出流已经关闭。