SXSSF 工作簿 createSheet() 在 linux 环境中失败

Posted

技术标签:

【中文标题】SXSSF 工作簿 createSheet() 在 linux 环境中失败【英文标题】:SXSSF workbook createSheet() fails on linux environments 【发布时间】:2018-08-05 23:01:23 【问题描述】:

正在尝试在使用 apache POI 3.17 的应用上实现 excel 导出功能。

在我的本地 tomcat 服务器和 Windows 开发环境上一切正常。但是,SXSSFWorkbook workbook.createSheet() 方法在 linux tomcat 服务器上失败,没有抛出任何有意义的错误(它只是挂起)。

奇怪的是,XSSFWorkbook createSheet 类上的相同方法可以正常工作。下面是代码的sn-ps。有没有人遇到过类似的问题?

    final SXSSFWorkbook workbook = new SXSSFWorkbook();
    workbook.setCompressTempFiles(true);
    SXSSFSheet sheet = workbook.createSheet("Sheet 1"); //this method fails

    final XSSFWorkbook workbook = new XSSFWorkbook();
    Sheet sheet = workbook.createSheet("Sheet 1"); // this works fine

编辑

我创建了一个自定义 TempFileCreationStrategy 以确保 tomcat 将文件写入它具有完全访问权限的目录。我可以看到文件已创建,但它在尝试将任何数据写入文件时挂起。

这个我想不通。

编辑2

我已启用 POI 日志记录,但我仍然没有得到任何可以调查的有意义的东西。在我的本地服务器 POI 记录开始写入文件时会吐出以下内容:

[20:13:05,005]DEBUG (?:?) - Save core properties part
[20:13:05,005]DEBUG (?:?) - Save package relationships
[20:13:05,005]DEBUG (?:?) - Save content types part
[20:13:05,005]DEBUG (?:?) - Save part 'docProps/app.xml'
[20:13:05,005]DEBUG (?:?) - Save part 'docProps/core.xml'
[20:13:05,005]DEBUG (?:?) - Save part 'xl/sharedStrings.xml'
[20:13:05,005]DEBUG (?:?) - Save part 'xl/styles.xml'
[20:13:05,005]DEBUG (?:?) - Save part 'xl/workbook.xml'
[20:13:05,005]DEBUG (?:?) - Save part 'xl/worksheets/sheet1.xml'

在 Linux 机器上,它甚至没有达到第一个日志输出的程度。需要找到一种方法来获取有关失败的更多详细信息!

编辑3

除了我在下面启用的默认日志记录之外,是否可以获得更详细的日志记录?

System.setProperty("org.apache.poi.util.POILogger", "org.apache.poi.util.SystemOutLogger" );

String tmpDir = System.getProperty("java.io.tmpdir")+File.separator+"excelfiles";
ExcelFileCreationStrategy tfcs = new ExcelFileCreationStrategy();

try 
    tfcs.createTempDirectory(tmpDir);
 catch (IOException e) 
    e.printStackTrace();
    LOG.error(e);


TempFile.setTempFileCreationStrategy(tfcs);

final SXSSFWorkbook workbook = new SXSSFWorkbook();
workbook.setCompressTempFiles(true);

LOG.debug("creating work sheet - next line fails");
Sheet sheet = workbook.createSheet(); //hangs here
LOG.debug("It's worked!!!!");

【问题讨论】:

你可以在问题挂起时添加堆栈跟踪吗? IE。通过 jstack ? 某处一定有例外。浏览所有相关的日志文件。 SXSSFWorkbook 默认使用System.getProperty("java.io.tmpdir") 中的临时文件。也许访问这是问题所在? SXSSF 在 Linux 上运行良好,因为这是所有 Apache POI 持续集成单元测试的默认平台!您一定是在该特定机器上错误配置了 Tomcat 或 Java @AxelRichter 所有日志都转储到 catalina.out 文件中,但我确实没有看到任何异常。我将其配置为写入我自己的自定义目录,确保 tomcat 具有完全的 rw 访问权限。它创建一个 .xml 文件,该文件是流操作的一部分,但似乎没有将任何数据写入文件。它在这一点上挂起。我被难住了! “它创建了一个 .xml 文件”:这令人惊讶。由于您使用的是workbook.setCompressTempFiles(true);,它应该创建一个*.gz 文件而不是*.xml 文件。确定我们在谈论相同的代码? 【参考方案1】:

我用 strace 检查了幕后发生的事情,相关的输出是:

11924 openat(AT_FDCWD, "/tmp/out.bin", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 48
11924 openat(AT_FDCWD, "/tmp/poifiles/poi-sxssf-template2618545805950425148.xlsx", O_RDWR|O_CREAT|O_EXCL, 0666) = 49
11924 openat(AT_FDCWD, "/tmp/poifiles/poi-sxssf-template2618545805950425148.xlsx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 49
11924 openat(AT_FDCWD, "/tmp/poifiles/poi-sxssf-template2618545805950425148.xlsx", O_RDONLY) = 49
11924 openat(AT_FDCWD, "/tmp/poifiles/poi-sxssf-sheet-xml261863645047955641.gz", O_RDONLY) = 21

我猜你需要确保/tmp/poifiles 可以被你的用户写入。但是在我的情况下,当我使它不可写时,应用程序不会挂起,而是抛出 IOException

或者,如果您的java.io.tmpdir 不是/tmp,我想您需要确保java.io.tmpdir 中的poifiles 子目录是可写的。

【讨论】:

感谢@BaRoN,我在测试解决方案时已经更改了目录(尽管 tomcat 具有对 /tmp 目录的完全读写访问权限)。不幸的是,我不得不把这个换成 XSSF 编写器,但它要慢得多,我需要将它限制在 100k 左右的记录以保留堆。 linux 机器是受保护的服务器,这意味着我需要通过中间件团队进行调试,这使过程更加复杂。【参考方案2】:

我也遇到了同样的问题,经过长时间的调试和分析,“bug”是在流式传输时,它尝试使用字体来确定字符的宽度来调整列。这会在没有消息的情况下失败,如果无法创建/确定字体,则会简单地中止创建。我能找到的唯一解决方案是安装包“fontconfig”。

sudo apt-get update
sudo apt-get install fontconfig

不幸的是,没有包 java 无法使用 java.awt.Fonts。

【讨论】:

以上是关于SXSSF 工作簿 createSheet() 在 linux 环境中失败的主要内容,如果未能解决你的问题,请参考以下文章

NPOI 工作簿一般设置

NPOI之Excel——合并单元格设置样式输入公式

NPOI之Excel——合并单元格设置样式输入公式

NPOI导出Excel合并表头写入公式

NPOI之Excel——合并单元格设置样式输入公式设置筛选等

POI操作Excel