将上传的文件保存在servlet应用程序中的推荐方法 [英] Recommended way to save uploaded files in a servlet application

查看:219
本文介绍了将上传的文件保存在servlet应用程序中的推荐方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  • 保存文件的最佳位置是什么?我应该将它保存在 / WEB-INF / uploads (建议不要这里< a>)或 $ CATALINA_BASE 下的某个位置(请参阅此处)或...? JavaEE 6教程从用户获取路径( :跆拳道:)。注意:该文件不应该以任何方式下载。

  • 我应该按照详细的这里?我会欣赏一些代码(我宁愿给它一个相对路径 - 所以它至少是Tomcat的便携式) - Part.write() 看起来很有前途 - 但显然需要一个绝对路径 >


    不幸的是,专注于下载文件,而他的回答上传文件跳过部分保存文件的位置。

    这个解决方案很容易转换为使用DB或JCR实现(如 jackrabbit )将是首选e。

    解决方案

    将其存储在IDE的项目文件夹(除了部署文件夹,在上载的图像仅在刷新后可用页面



    1. IDE的项目文件夹中的更改不会立即得到反映在服务器的工作文件夹中。在IDE中有一种后台作业,它注意到服务器的工作文件夹与上次更新(在IDE中称为发布)是同步的。这是你看到的问题的主要原因。在现实世界的代码中存在的情况下,上传的文件存储在webapp的部署文件夹将无法正常工作在所有。一些服务器(默认或通过配置)不会将已部署的WAR文件扩展到本地磁盘文件系统,而是完全在内存中。如果没有基本上编辑已部署的WAR文件并重新部署它,则无法在内存中创建新文件。
      即使服务器将部署的WAR文件展开为本地磁盘文件系统,所有新创建的文件在重新部署或甚至简单重新启动时都会丢失,只是因为这些新文件不是原始WAR文件的一部分。


    >

    对于我或其他任何在本地磁盘文件系统中将被保存的人来说,只要你不是曾经使用 getRealPath()方法。使用该方法可以在任何情况下报警。

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

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


    • Hardcoded:

       文件上传=新文件(/ path / to / uploads ); 


    • 环境变量通过 SET UPLOAD_LOCATION = / path / to / uploads

       文件上传=新文件(System.getenv(UPLOAD_LOCATION)); 


    • 通过 -Dupload.location = / path / to / uploads
      $ b

       文件上传=新建文件(System.getProperty( upload.location)); 


    • *。properties upload.location = / path / to / uploads

       文件uploads = new File(properties.getProperty(upload.location)); 


    • web.xml upload.location 和值 / path / to / uploads < context-param> / code>:

       文件上传=新文件(getServletContext()。getInitParameter(upload.location)) ; 


    • 如果有,请使用服务器提供的位置。在 JBoss AS / WildFly

       文件上传=新文件(System.getProperty(jboss.server。 data.dir),上传); 




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

      File file = new File(uploads,somefilename.ext); (InputStream input = part.getInputStream()){
    Files.copy(input,file.toPath());







    $ b

    或者,当你想自动生成一个唯一的文件名来防止用户覆盖现存的文件名字相同:

    $ p $ 文件文件= File.createTempFile(somefilename-,.ext,uploads );
    $ b $ try(InputStream input = part.getInputStream()){
    Files.copy(input,file.toPath(),StandardCopyOption.REPLACE_EXISTING);

    $ / code>

    如何获得部分在JSP / Servlet中的答案在如何上传文件到服务器使用JSP / Servlet ?,以及如何在JSF中获取部分



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

    另请参阅:




    I read here that one should not save the file in the server anyway as it is not portable, transactional and requires external parameters. However, given that I need a tmp solution for tomcat (7) and that I have (relative) control over the server machine I want to know :

    • What is the best place to save the file ? Should I save it in /WEB-INF/uploads (advised against here) or someplace under $CATALINA_BASE (see here) or ... ? The JavaEE 6 tutorial gets the path from the user (:wtf:). NB : The file should not be downloadable by any means.

    • Should I set up a config parameter as detailed here ? I'd appreciate some code (I'd rather give it a relative path - so it is at least Tomcat portable) - Part.write() looks promising - but apparently needs a absolute path

    • I'd be interested in an exposition of the disadvantages of this approach vs a database/JCR repository one

    Unfortunately the FileServlet by @BalusC concentrates on downloading files, while his answer on uploading files skips the part on where to save the file.

    A solution easily convertible to use a DB or a JCR implementation (like jackrabbit) would be preferable.

    解决方案

    Store it anywhere in an accessible location except of the IDE's project folder aka the server's deploy folder, for reasons mentioned in the answer to Uploaded image only available after refreshing the page:

    1. Changes in the IDE's project folder does not immediately get reflected in the server's work folder. There's kind of a background job in the IDE which takes care that the server's work folder get synced with last updates (this is in IDE terms called "publishing"). This is the main cause of the problem you're seeing.

    2. In real world code there are circumstances where storing uploaded files in the webapp's deploy folder will not work at all. Some servers do (either by default or by configuration) not expand the deployed WAR file into the local disk file system, but instead fully in the memory. You can't create new files in the memory without basically editing the deployed WAR file and redeploying it.

    3. Even when the server expands the deployed WAR file into the local disk file system, all newly created files will get lost on a redeploy or even a simple restart, simply because those new files are not part of the original WAR file.

    It really doesn't matter to me or anyone else where exactly on the local disk file system it will be saved, as long as you do not ever use getRealPath() method. Using that method is in any case alarming.

    The path to the storage location can in turn be definied in many ways. You have to do it all by yourself. Perhaps this is where your confusion is caused because you somehow expected that the server does that all automagically. Please note that @MultipartConfig(location) does not specify the final upload destination, but the temporary storage location for the case file size exceeds memory storage threshold.

    So, the path to the final storage location can be definied in either of the following ways:

    • Hardcoded:

      File uploads = new File("/path/to/uploads");
      

    • Environment variable via SET UPLOAD_LOCATION=/path/to/uploads:

      File uploads = new File(System.getenv("UPLOAD_LOCATION"));
      

    • VM argument during server startup via -Dupload.location="/path/to/uploads":

      File uploads = new File(System.getProperty("upload.location"));
      

    • *.properties file entry as upload.location=/path/to/uploads:

      File uploads = new File(properties.getProperty("upload.location"));
      

    • web.xml <context-param> with name upload.location and value /path/to/uploads:

      File uploads = new File(getServletContext().getInitParameter("upload.location"));
      

    • If any, use the server-provided location, e.g. in JBoss AS/WildFly:

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

    Either way, you can easily reference and save the file as follows:

    File file = new File(uploads, "somefilename.ext");
    
    try (InputStream input = part.getInputStream()) {
        Files.copy(input, file.toPath());
    }
    

    Or, when you want to autogenerate an unique file name to prevent users from overwriting existing files with coincidentally the same name:

    File file = File.createTempFile("somefilename-", ".ext", uploads);
    
    try (InputStream input = part.getInputStream()) {
        Files.copy(input, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
    }
    

    How to obtain part in JSP/Servlet is answered in How to upload files to server using JSP/Servlet? and how to obtain part in JSF is answered in How to upload file using JSF 2.2 <h:inputFile>? Where is the saved File?

    Note: do not use Part#write() as it interprets the path relative to the temporary storage location defined in @MultipartConfig(location).

    See also:

    这篇关于将上传的文件保存在servlet应用程序中的推荐方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆