2020-04-21 13:42:12.324 [http-nio-5556-exec-1] (AutoShelfServiceImpl.java:41): DEBUG com.ybjdw.tool.service.impl.AutoShelfServiceImpl - 本次上架共花费时间:12918
2020-04-21 13:42:12.327 [http-nio-5556-exec-1] (BasicExcelUtil.java:212): INFO com.ybjdw.tool.utils.BasicExcelUtil - 开始生成excel,excel路径:/home/tool/data/tmp/20200421134212商品资料统一范本-星梦依.xlsx
2020-04-21 13:42:12.532 [http-nio-5556-exec-1] (BasicExcelUtil.java:232): DEBUG com.ybjdw.tool.utils.BasicExcelUtil - java.io.IOException: 权限不够
现象: 使用SXSSFWorkbook.write(bos)输入excel文件,提示权限不够,目前流所在文件路径都是有权限的。
操作:前面使用root账户运行了一次该工程,后续使用指定用户启动,就报错。
原因:查看写出excel具体方法代码
public void write(OutputStream stream) throws IOException
{
flushSheets();
//Save the template
File tmplFile = TempFile.createTempFile("poi-sxssf-template", ".xlsx");
boolean deleted;
try {
FileOutputStream os = new FileOutputStream(tmplFile);
try {
_wb.write(os);
} finally {
os.close();
}
//Substitute the template entries with the generated sheet data files
final ZipEntrySource source = new ZipFileZipEntrySource(new ZipFile(tmplFile));
injectData(source, stream);
} finally {
deleted = tmplFile.delete();
}
if(!deleted) {
throw new IOException("Could not delete temporary file after processing: " + tmplFile);
}
}
private void createPOIFilesDirectory() throws IOException {
// Identify and create our temp dir, if needed
// The directory is not deleted, even if it was created by this TempFileCreationStrategy
if (dir == null) {
String tmpDir = System.getProperty(JAVA_IO_TMPDIR);
if (tmpDir == null) {
throw new IOException("Systems temporary directory not defined - set the -D"+JAVA_IO_TMPDIR+" jvm property!");
}
dir = new File(tmpDir, POIFILES);
}
createTempDirectory(dir);
}
其中使用到了TempFile.createTempFile("poi-sxssf-template", ".xlsx");这将在linux系统的/tmp路径下创建一个poifiles文件夹,第一次root用户启动后,就已经创建了,后续使用另一个低权限用户再次启动,就会出问题;由此联想到了,如果linux上有2个不同用户启动的工程,使用excel导出,届时也将出现问题。
解决方案:
1.简单粗暴
修改/tmp/poifiles文件夹所归属的用户。
chown -R tool:tool /tmp/poifiles
2.稍微优雅点
不同工程用户启动指定不同临时文件目录;查看使用的临时文件目录路径
public final class TempFile {
/** The strategy used by {@link #createTempFile(String, String)} to create the temporary files. */
private static TempFileCreationStrategy strategy = new DefaultTempFileCreationStrategy();
/** Define a constant for this property as it is sometimes mistypes as "tempdir" otherwise */
public static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
private TempFile() {
// no instances of this class
}
从TempFile类中可查看到使用的临时文件目录为java.io.tmpdir所指的路径。
在启动java工程时通过 -Djava.io.tmpdir=/home/tool/tmp指定。
ps:临时文件路径若不存在,程序会自动创建;同时临时文件的删除也是可以设置的。