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。通过 jstackSXSSFWorkbook
默认使用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 环境中失败的主要内容,如果未能解决你的问题,请参考以下文章