以块的形式发送Excel文件时遇到问题。我有这样一段代码,它应该做这件事,它的工作很好,到一定程度。但是,问题是它只写入前100条记录。在此之后,文件大小保持不变,就像它有所有10,000条记录一样,但当打开时,它只有100条记录。
@Override
public void generateAndSendExcelChunks(ServletOutputStream outputStream) throws IOException {
Workbook workbook = new SXSSFWorkbook();
Sheet sheet = workbook.createSheet("Datos");
int totalRows = 10000;
int rowsPerChunk = 100;
int currentRow = 0;
while (currentRow < totalRows) {
int endRow = currentRow + rowsPerChunk;
endRow = Math.min(endRow, totalRows);
generateChunkData(sheet, currentRow, endRow);
workbook.write(outputStream);
outputStream.flush();
sheet = workbook.createSheet("Datos");
currentRow = endRow;
}
workbook.close();
}
private void generateChunkData(Sheet sheet, int startRow, int endRow) {
for (int i = startRow; i < endRow; i++) {
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
cell.setCellValue("Valor " + (i + 1));
}
}
sheet = workbook.createSheet("Datos");
行不起作用,因为它试图创建一个名称已经存在的工作表。如果我试图获取对该工作表的引用,它会在这一行给出一个"stream closed"错误:workbook.write(outputStream);
。预期功能是将所有信息存储在同一工作表中,而不覆盖任何内容。
2条答案
按热度按时间mnemlml81#
你可以使用另一种方法。您可以将Excel文件拆分为二进制块并发送它们。然后接收端可以根据每个块的名称将它们放在一起
发送者:
接收方:
mnowg1ta2#
你想做的事是不可能的。至少到目前为止还没有使用Apache POI。
Office Open XML文件(如
*.xlsx
文件)也是包含特殊内部文件结构中的数据的ZIP存档。ZIP压缩文件包含*.xml
文件和其他文件也在一个特殊的目录结构。不同的部分彼此相关。关系存储在*.rel
文件中,该文件存储特殊的关系XML。例如,如果简单地解压缩*.xlsx
文件,就可以看到这一点。7-Zip默认可以这样做,使用其他ZIP-Software需要重命名文件*.zip
。在知道这一点并看到这个结构之后,考虑如何考虑所有的关系来填充这个块。总结:非常困难,几乎不可能。
打开任何类型的
Workbook
对象都会打开该ZIP存档并将内部存储的文件读入内存。Workbook.write
将完整的内部ZIP内容写入文件。因此,在Workbook.write
之后,工作簿对象在再次打开之前不会变得更有用。因此,在循环中使用它,如:将第一内容放入,写入,将第二内容放入,写入,…不可能一定是这样的:打开工作簿,放入第一个内容,写入,关闭工作簿,打开工作簿,放入第二个内容,写入,关闭工作簿,...但这与您的需求相矛盾,因为打开工作簿总是将所有内容读入内存。但是为什么不像程序员所想的那样简单地使用
SXSSFWorkbook
呢?参见SXSSF(流用户模型API)。使用默认属性,这正是您要做的。它只在内存中保留100行图纸数据。其他图纸数据将写入临时图纸XML文件中。只有其他数据和关系永久保留在内存中。完成后,SXSSFWorkbook.write
使用临时存储的工作表数据合成ZIP存档。当然
SXSSFWorkbook.write
也需要写整个*.xlsx
-ZIP-archive。因此,如果您的问题是将一个大文件发送到客户端,那么使用SXSSFWorkbook.write
在服务器端存储*.xlsx
文件。然后把它想象成一个大的二进制文件,交付(提供下载)给客户端。应该有默认的方法来解决这种任务,因为这是一个默认的任务。自我编程划分成块是没有必要的,是一个坏主意,在我看来。