12

我开发了一个 Java EE Web 应用程序。此应用程序允许用户在浏览器的帮助下上传文件。一旦用户上传了他的文件,这个应用程序首先将上传的文件存储在服务器上(它正在运行),然后处理它。

目前,我将文件存储在服务器上,如下所示:

try {
    // formFile represents the uploaded file
    FormFile formFile = programForm.getTheFile();
    String path = getServlet().getServletContext().getRealPath("") + "/"
        + formFile.getFileName();
    System.out.println(path);
    file = new File(path);
    outputStream = new FileOutputStream(file);
    outputStream.write(formFile.getFileData());
}

其中,formFile代表上传的文件。

现在,问题是它在某些服务器上运行良好,但在某些服务器上getServlet().getServletContext().getRealPath("")正在返回null,所以我得到的最终路径是null/filename并且文件没有存储在服务器上。

当我检查 API 的ServletContext.getRealPath()方法时,我发现了以下内容:

public java.lang.String getRealPath(java.lang.String path)

返回包含给定虚拟路径的真实路径的字符串。例如,"/index.html"返回服务器文件系统上的绝对文件路径的路径将由请求提供服务"http://host/contextPath/index.html",其中 contextPath 是此 ServletContext 的上下文路径。

返回的真实路径将采用适合运行 servlet 容器的计算机和操作系统的格式,包括正确的路径分隔符。如果 servlet 容器由于任何原因(例如当内容从 .war 存档中可用时)无法将虚拟路径转换为真实路径,则此方法返回 null。

那么,有没有其他方法可以将文件存储在那些服务器上也null返回getServlet().getServletContext().getRealPath("")

4

2 回答 2

21

根据规范,您可以保证从 servlet 容器中获得的唯一“真实”路径是临时目录。

您可以通过ServletContext.gerAttribute("javax.servlet.context.tempdir"). 但是,这些文件对 Web 上下文不可见(即,您不能发布简单的 URL 来传递这些文件),并且无法保证这些文件在 Web 应用程序或服务器重新启动后仍然存在。

如果您只是需要一个地方来短期存储工作文件,那么这对您来说很好。

如果你真的需要一个目录,你可以将它作为一个配置参数(环境变量、Java 属性(即java -Dyour.file.here=/tmp/files ...)、web.xml 中设置的上下文参数、通过 Web 表单存储在数据库中的配置参数等.)。然后由部署者为您设置此目录。

但是,如果您需要稍后实际提供该文件,您将需要一个特定于容器的机制来将外部目录“挂载”到您的 Web 应用程序中(Glassfish 作为“备用文档根”,其他人有类似的概念),或者您将需要编写一个 servlet/filter 来在您的 Web 应用程序之外提供文件存储。这个FileServlet非常完整,正如您所见,创建自己的文件虽然不难,但要正确完成并非易事。

编辑:

基本要点是相同的,但不是使用“getRealPath”,而是简单地使用“getInitParameter”。

所以:

String filePath = getServletContext().getInitParameter("storedFilePath") + "/" + fileName;

并在路上。

再次编辑:

至于路径的内容,我给它一个绝对路径。否则,您需要知道应用服务器在执行期间将其默认路径设置在哪里,并且每个应用服务器可能使用不同的目录。例如,我认为 Glassfish 的工作目录是运行域的配置目录。不是一个特别明显的选择。

所以,绝对使用绝对路径。这样您就可以知道文件的去向,并且可以在必要时控制该目录的操作系统级别的访问权限。

于 2010-04-18T17:50:09.483 回答
13

不建议从 Java EE 容器写入文件系统,尤其是在您需要处理写入的数据时:

  • 它不是事务性的
  • 它损害了可移植性(如果您在集群环境中怎么办)
  • 它需要为目标位置设置外部参数

如果这是一个选项,我会将文件存储在数据库中或使用 JCR 存储库(如Jackrabbit)。

于 2010-04-18T20:37:56.157 回答