Tomcat 在servlet应用程序中保存上载文件的推荐方法

Tomcat 在servlet应用程序中保存上载文件的推荐方法,tomcat,servlets,file-upload,servlet-3.0,Tomcat,Servlets,File Upload,Servlet 3.0,我了解到,无论如何都不应该将文件保存在服务器中,因为它不是可移植的、事务性的,并且需要外部参数。但是,考虑到我需要一个针对tomcat(7)的tmp解决方案,并且我对服务器机器拥有(相对)控制权,我想知道: 保存文件的最佳位置是什么?我应该把它保存在/WEB-INF/uploads(建议不要)或$CATALINA_BASE下的某个地方(请参阅)还是?JavaEE6教程(:wtf:)。注意:该文件不应以任何方式下载 我应该设置一个配置参数吗?我很欣赏一些代码(我宁愿给它一个相对路径——因此它至少

我了解到,无论如何都不应该将文件保存在服务器中,因为它不是可移植的、事务性的,并且需要外部参数。但是,考虑到我需要一个针对tomcat(7)的tmp解决方案,并且我对服务器机器拥有(相对)控制权,我想知道:

  • 保存文件的最佳位置是什么?我应该把它保存在
    /WEB-INF/uploads
    (建议不要)或
    $CATALINA_BASE
    下的某个地方(请参阅)还是?JavaEE6教程(:wtf:)。注意:该文件不应以任何方式下载

  • 我应该设置一个配置参数吗?我很欣赏一些代码(我宁愿给它一个相对路径——因此它至少是Tomcat可移植的)——看起来很有希望——但显然需要一个绝对路径

  • 我想解释一下这种方法相对于数据库/JCR存储库的缺点

不幸的是,@BalusC专注于下载文件,而他在上传文件时忽略了保存文件的部分


最好是一个易于转换为使用DB或JCR实现(如)的解决方案。

将其存储在除IDE的项目文件夹(又称服务器的部署文件夹)以外的任何可访问位置,原因如下:

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

  • 在真实代码中,在某些情况下,将上载的文件存储在webapp的deploy文件夹中根本不起作用。有些服务器(默认或配置)不会将部署的WAR文件扩展到本地磁盘文件系统,而是完全在内存中。如果不编辑已部署的WAR文件并重新部署它,就无法在内存中创建新文件

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

  • 对我或其他任何人来说,它在本地磁盘文件系统的确切位置将被保存并不重要,只要您愿意。无论如何,使用这种方法是令人震惊的

    存储位置的路径可以通过多种方式定义。你必须自己做这一切。也许这就是造成您困惑的原因,因为您不知何故期望服务器自动完成这一切。请注意,
    @MultipartConfig(location)
    没有指定最终上载目标,但是案例文件大小的临时存储位置超过了内存存储阈值

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

    • 硬编码:

        File uploads = new File("/path/to/uploads");
      
    • 环境变量通过
      设置上传位置=/path/to/uploads

        File uploads = new File(System.getenv("UPLOAD_LOCATION"));
      
        File uploads = new File(System.getProperty("upload.location"));
      
        File uploads = new File(properties.getProperty("upload.location"));
      
        File uploads = new File(getServletContext().getInitParameter("upload.location"));
      
    • 通过
      -Dupload.location=“/path/to/uploads”
      启动服务器期间的VM参数:

    • *.properties
      文件条目为
      upload.location=/path/to/uploads

        File uploads = new File(System.getenv("UPLOAD_LOCATION"));
      
        File uploads = new File(System.getProperty("upload.location"));
      
        File uploads = new File(properties.getProperty("upload.location"));
      
        File uploads = new File(getServletContext().getInitParameter("upload.location"));
      
    • web.xml
      名称
      upload.location
      和值
      /path/to/uploads

        File uploads = new File(System.getenv("UPLOAD_LOCATION"));
      
        File uploads = new File(System.getProperty("upload.location"));
      
        File uploads = new File(properties.getProperty("upload.location"));
      
        File uploads = new File(getServletContext().getInitParameter("upload.location"));
      
    • 如果有,请使用服务器提供的位置,例如:

    无论哪种方式,您都可以按如下方式轻松引用和保存文件:

    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
    ,以及如何在JSF中获取
    part
    在中得到了回答

    注意:请勿使用,因为它解释了相对于
    @MultipartConfig(location)
    中定义的临时存储位置的路径。另外,在读/写过程中,不正确地使用
    读卡器
    /
    写卡器
    而不是
    输入流
    /
    输出流
    将字节转换为字符,从而绝对确保不会损坏二进制文件,如PDF文件或图像文件

    另见:
    • (JSF目标明确,但原理基本相同)
    • (如果你想把它送回去)

    将其存储在可访问位置的任何位置,IDE的项目文件夹即服务器的部署文件夹除外,原因如下:

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

  • 在真实代码中,在某些情况下,将上载的文件存储在webapp的deploy文件夹中根本不起作用。有些服务器(默认或配置)不会将部署的WAR文件扩展到本地磁盘文件系统,而是完全在内存中。如果不编辑已部署的WAR文件并重新部署它,就无法在内存中创建新文件

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

  • 对我或其他任何人来说,它在本地磁盘文件系统的确切位置将被保存并不重要,只要您愿意。无论如何,使用这种方法是令人震惊的

    存储位置的路径可以通过多种方式定义。尤哈