一尘不染

将上传文件保存在Servlet应用程序中的推荐方法

tomcat

无论如何都不应该将文件保存在服务器中,因为该文件不可移植,具有事务性并且需要外部参数。但是,鉴于我需要一个适用于tomcat(7)的tmp解决方案,并且可以(相对)控制我想知道的服务器计算机:

  • 保存文件的最佳位置是什么?我应该将其保存在/WEB-INF/uploads是下面$CATALINA_BASE或…的某个位置?JavaEE 6教程从用户(:wtf :) 获取路径。注意:该文件不应以任何方式下载。

  • 是否应按详细说明设置配置参数?我会喜欢一些代码(我希望给它一个相对路径-因此它至少是Tomcat可移植的)- Part.write()看起来很有希望-但显然需要一个绝对路径

  • 我想对这种方法相对于数据库/ JCR存储库的缺点进行阐述。

不幸的是 ,@ BalusC 的FileServlet专注于下载文件,而他对上传文件的回答忽略了保存文件的位置。

易于转换为使用DB或JCR实现的解决方案(如jackrabbit)将是可取的。


阅读 383

收藏
2020-06-16

共1个答案

一尘不染

将其存储在IDE的项目文件夹(又称为服务器的deploy文件夹) 以外
的可访问位置的任何位置,出于“上载映像”答案中提到的原因,仅在刷新页面后可用:

1.
IDE的项目文件夹中的更改不会立即反映在服务器的工作文件夹中。IDE中有一种后台作业,用于确保服务器的工作文件夹与上次更新同步(这在IDE中称为“发布”)。这是您遇到问题的主要原因。

2.
在现实世界中的代码中,有时无法将上传的文件存储在webapp的deploy文件夹中。某些服务器(默认情况下或通过配置)不会将已部署的WAR文件扩展到本地磁盘文件系统中,而是完全扩展到内存中。如果没有基本编辑已部署的WAR文件并重新部署它,就无法在内存中创建新文件。

3.
即使服务器将已部署的WAR文件扩展到本地磁盘文件系统中,所有新创建的文件也将在重新部署甚至是简单的重新启动时丢失,这仅仅是因为这些新文件不属于原始WAR文件。

这其实并不重要,对我或其他人那里正是本地磁盘文件系统将被保存,只要你做 曾经使用过getRealPath()的方法。在 任何
情况下,使用该方法都是令人震惊的。

到存储位置的路径又可以通过多种方式定义。你必须全部由做 自己
。也许这是造成您困惑的原因,因为您以某种方式期望服务器自动完成所有操作。请注意,@MultipartConfig(location)没有
指定最后上传目的地,但对于案件的文件大小的临时存储位置超过存储器阈值。

因此,可以通过以下两种方式定义最终存储位置的路径:

  • 硬编码:

    File uploads = new File("/path/to/uploads");
    
  • 环境变量通过SET UPLOAD_LOCATION=/path/to/uploads

    File uploads = new File(System.getenv("UPLOAD_LOCATION"));
    
  • 通过-Dupload.location="/path/to/uploads"以下命令在服务器启动期间的VM参数:

    File uploads = new File(System.getProperty("upload.location"));
    
  • *.properties文件输入为upload.location=/path/to/uploads

    File uploads = new File(properties.getProperty("upload.location"));
    
  • web.xml <context-param>具有名称upload.location和值/path/to/uploads

    File uploads = new File(getServletContext().getInitParameter("upload.location"));
    
  • 如果有,请使用服务器提供的位置,例如在JBoss AS / WildFly中:

    File uploads = new File(System.getProperty("jboss.server.data.dir"), "uploads");
    

无论哪种方式,您都可以轻松地参考并保存文件,如下所示:

File file = new File(uploads, "somefilename.ext");

try (InputStream input = part.getInputStream()) {
    Files.copy(input, file.toPath());
}

或者,当您要自动生成唯一的文件名以防止用户覆盖名称恰好相同的现有文件时:

File file = File.createTempFile("somefilename-", ".ext", uploads);

try (InputStream input = part.getInputStream()) {
    Files.copy(input, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}

如何使用JSP / Servlet将文件上传到服务器,part回答了如何在JSP /
Servlet中获取文件?以及如何使用JSF 2.2
上传文件中part回答了如何在JSF中获取文件?保存的文件在哪里?

注意:千万 不能
使用Part#write(),因为它相对于定义的临时存储位置的路径解释@MultipartConfig(location)

2020-06-16