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

我在这里读到,不应该将文件保存在服务器中,因为它不是可移植的,事务性的并且需要外部参数。 然而,鉴于我需要一个tomcat(7)的tmp解决方案,并且我有(相对)我想知道的服务器机器的控制权:

  • 什么是保存文件的最佳地点? 我应该将它保存在/WEB-INF/uploads (在这里建议)还是在$CATALINA_BASE (见这里)或...下的某个地方? JavaEE 6教程获取用户的路径(:wtf :)。 注意:文件不得以任何方式下载。

  • 我应该如何设置配置参数? 我会欣赏一些代码(我宁愿给它一个相对路径 - 所以它至少是Tomcat的便携式) - Part.write()看起来很有前途 - 但显然需要一个绝对路径

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

  • 不幸的是@BalusC的FileServlet专注于下载文件,而他关于上传文件的回答则跳过了保存文件的部分。

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


    将其存储在IDE的项目文件夹(即服务器的部署文件夹除外)的可访问位置的任何位置,原因仅限于刷新页面后可用的上载映像的答案中提到的原因:

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

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

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

  • 只要你没有使用过getRealPath()方法,对于我或者其他任何在本地磁盘文件系统中将被保存的人来说都没有 getRealPath() 。 无论如何,使用这种方法都是令人担忧的。

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

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

  • 硬编码:

    File uploads = new File("/path/to/uploads");
    
  • 通过SET UPLOAD_LOCATION=/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和value /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);
    }
    

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

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

    也可以看看:

  • 如何将上传的文件保存在JSF中(JSF定位,但原理几乎相同)
  • 在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法(如果您想要将其提供回去)
  • 如何在基于servlet的Web应用程序中临时保存生成的文件

  • 我根据公认的答案发布我的最终做法:

    @SuppressWarnings("serial")
    @WebServlet("/")
    @MultipartConfig
    public final class DataCollectionServlet extends Controller {
    
        private static final String UPLOAD_LOCATION_PROPERTY_KEY="upload.location";
        private String uploadsDirName;
    
        @Override
        public void init() throws ServletException {
            super.init();
            uploadsDirName = property(UPLOAD_LOCATION_PROPERTY_KEY);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            // ...
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            Collection<Part> parts = req.getParts();
            for (Part part : parts) {
                File save = new File(uploadsDirName, getFilename(part) + "_"
                    + System.currentTimeMillis());
                final String absolutePath = save.getAbsolutePath();
                log.debug(absolutePath);
                part.write(absolutePath);
                sc.getRequestDispatcher(DATA_COLLECTION_JSP).forward(req, resp);
            }
        }
    
        // helpers
        private static String getFilename(Part part) {
            // courtesy of BalusC : http://stackoverflow.com/a/2424824/281545
            for (String cd : part.getHeader("content-disposition").split(";")) {
                if (cd.trim().startsWith("filename")) {
                    String filename = cd.substring(cd.indexOf('=') + 1).trim()
                            .replace(""", "");
                    return filename.substring(filename.lastIndexOf('/') + 1)
                            .substring(filename.lastIndexOf('') + 1); // MSIE fix.
                }
            }
            return null;
        }
    }
    

    其中:

    @SuppressWarnings("serial")
    class Controller extends HttpServlet {
    
        static final String DATA_COLLECTION_JSP="/WEB-INF/jsp/data_collection.jsp";
        static ServletContext sc;
        Logger log;
        // private
        // "/WEB-INF/app.properties" also works...
        private static final String PROPERTIES_PATH = "WEB-INF/app.properties";
        private Properties properties;
    
        @Override
        public void init() throws ServletException {
            super.init();
            // synchronize !
            if (sc == null) sc = getServletContext();
            log = LoggerFactory.getLogger(this.getClass());
            try {
                loadProperties();
            } catch (IOException e) {
                throw new RuntimeException("Can't load properties file", e);
            }
        }
    
        private void loadProperties() throws IOException {
            try(InputStream is= sc.getResourceAsStream(PROPERTIES_PATH)) {
                    if (is == null)
                        throw new RuntimeException("Can't locate properties file");
                    properties = new Properties();
                    properties.load(is);
            }
        }
    
        String property(final String key) {
            return properties.getProperty(key);
        }
    }
    

    和/WEB-INF/app.properties:

    upload.location=C:/_/
    

    HTH,如果你发现一个错误让我知道

    链接地址: http://www.djcxy.com/p/46211.html

    上一篇: Recommended way to save uploaded files in a servlet application

    下一篇: ServletFileUpload#parseRequest(request) returns an empty list