【发布时间】:2020-02-24 04:37:33
【问题描述】:
我最近将一个 tomcat 应用程序从一个 Linux 服务器迁移到另一个。从那时起,我在新服务器上面临一个新的文件创建问题。在新服务器中,当我尝试创建文件时失败,在旧服务器中可以正常工作:
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile(); //this FAILS
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
为了调查这个问题,我使用以下方法打印了工作目录:
String cwd = new File("").getAbsolutePath();
System.out.println(cwd);
这个调试揭示了问题背后的根本原因: 旧服务器返回:var/lib/tomcat,而新服务器返回:/(根目录) 由于tomcat用户没有(也不应该)对根目录有写权限,所以创建文件失败。
我的问题,Tomcat的当前工作目录是由哪个因素决定的,如何配置?
这是我的 Tomcat 和 java 环境变量。
Environment="JAVA_HOME=/usr/lib/jvm/jre"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_HOME=/opt/tomcat"
更新:我尝试-Duser.dir 配置工作目录。使用这个之后,我从System.out.println(cwd); 得到了预期的结果。但问题仍然存在,文件创建失败。显然,这不适用于FileOutputStreams。
来源:Changing the current working directory in Java?
所有权和权限处理得当。我正在寻找一个系统端解决方案,无需更改任何代码,因为相同的代码在旧服务器中运行。
【问题讨论】:
-
Web 应用程序应该从不依赖工作目录。一个 servlet 容器可以为多个 Web 应用程序提供服务,否则它们可能需要不同的工作目录,而这不可能发生,因此永远不要依赖工作目录来处理 Web 应用程序中的任何内容。任何时候代码需要使用文件系统时,始终使用绝对路径,这本身应该是很少见的,除了临时文件。
-
如何 convFile.createNewFile();失败?异常和消息是什么?
-
您应该使用
ServletContext.getRealPath(),而不是当前工作目录,以便获得每个servlet的路径。 -
@jordiburgos 以下是详细信息:2019 年 10 月 25 日 11:52:37.029 严重 [ajp-nio-8009-exec-45] controller.FileUploadController.convert null java.io.IOException: Permission java.io.UnixFileSystem.createFileExclusively(Native Method) at java.io.File.createNewFile(File.java:1012) at ca.pbl.smart.controller.FileUploadController.convert(FileUploadController.java:449)
-
所以,“权限被拒绝”,更改您尝试创建新文件的文件夹。