代码之家  ›  专栏  ›  技术社区  ›  TheJediCowboy

Spring文件上传有问题

  •  9
  • TheJediCowboy  · 技术社区  · 14 年前

    我有以下代码块,用于处理我在SpringMVC Web应用程序中使用的照片的文件上传。我使用SpringMVCCommondMultipartFileResolver来处理文件上载。

    if(model.getPhoto() != null){
        if(!model.getPhoto().isEmpty()){
            MultipartFile file = model.getPhoto();
            String fileName = file.getOriginalFilename();
            String filePath = baseDirectory + fileName;
            FileOutputStream fos = new FileOutputStream(filePath);
             try 
             {
                fos.write(file.getBytes());
                agentProfile.setPhotoUri(fileName);
             } 
             catch (IllegalStateException e) 
             {
                System.out.println(e);
    
             }
             finally   
             {
                 fos.close();
             }
        }
    }
    

    在app-servlet.xml文件中,我有以下代码来配置多部分文件解析器bean。

     <bean id="multipartResolver"   class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     </bean>
    

    我上传照片时遇到一些随机问题。

    1)如果我要上传一张较小的照片,大约3kb左右,它将成功上传。

    2)如果我上传一张稍大一点的照片,它会在目录中创建文件,但大小为0字节,并会给出以下错误消息。

     java.lang.IllegalStateException: File has been moved - cannot be read again
    org.springframework.web.multipart.commons.CommonsMultipartFile.getBytes(CommonsMultipartFile.java:112)
    com.mmz.admin.mvc.controller.AddAgentController.processFinish(AddAgentController.java:145)
    org.springframework.web.servlet.mvc.AbstractWizardFormController.validatePagesAndFinish(AbstractWizardFormController.java:642)
    org.springframework.web.servlet.mvc.AbstractWizardFormController.processFormSubmission(AbstractWizardFormController.java:492)
    org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:265)
    org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    

    我尝试了几个不同的选项来配置多部分解析器,例如将其切换为处理 通用多部分文件 反对平原的物体 多部分文件 对象,但没有更改。

    我还尝试使用以下属性手动配置CommonMultipartFileResolver bean中的最大上载大小。

     <property name="maxUploadSize" value="1024000000"/>  
    

    也没什么变化。我不确定commons multipartresolver默认的文件大小,但这不是我的问题。

    有人告诉我,我遇到的问题是由于Spring使用的多部分解析器/处理程序中的问题。我最近有一篇关于这个问题的文章,因为发现了新的信息,我想用新的信息重新发布。旧邮件可在 CommonsMultipartFileResolver Problem

    我觉得我已经检查了互联网上几乎所有的资源,以找到更多的文档,但无法找出问题所在。

    请帮我弄清楚这是怎么回事,如果有更好的, 更简单 解决方案可能是探索者那些选项,但如果我能找到一个解决方案,我宁愿继续使用我当前的方法。

    编辑 注意-我一直在尝试上传不同尺寸的照片,我相信它允许我上传的限制在10 KB左右。任何大于10千字节的数据都会导致它断开,并给出上面的错误。

    3 回复  |  直到 10 年前
        1
  •  12
  •   TheJediCowboy    14 年前

    经过大量的研究,我解决了我的问题。结果表明,没有为您可以使用的最大字节数设置默认限制。 通用多部分文件解析程序 当然,通过设置以下属性,您可以在bean中为这个数量指定您想要的任何内容。

    <property name="maxUploadSize" value="99999999999"/>
    

    还有一个财产 最大化 这允许您指定将文件写入磁盘之前允许的最大大小。尽管这与最大上载大小的工作方式相同,但如果不指定数量,则默认为1024字节。如果我试图上传一个大文件,这就解释了它的破坏。

    为了允许上载超过1024字节的文件,您需要将maximemorysize值增加到您需要的值,如下所示…

    这就是解决我问题的方法。当我查看commonfileupload文档时,我了解到这个属性默认为1024。

    您可以在以下位置查看此文档: CommonsFileUpload Documentation

    我希望这对任何人都有帮助,因为没有很好的文档说明如何使用commonmultipartfile。

        2
  •  3
  •   splashout    11 年前

    我注意到这个错误只在文件超过1024字节时发生。 你试着读两遍文件 . 正如citadelcsalum所提到的,设置maximemorysize=maxuploadsize可以解决这个问题,但是应该记住内存使用。如果要考虑内存问题,另一个选项是在第一次读取时将多部分文件数据写入临时文件,然后使用该文件进行后续读取。如果你不读两遍,就不需要增加最大的内存大小。

        3
  •  2
  •   Robert N    10 年前

    您在问题中引用的异常状态为:“文件已移动-无法再次读取”。这是因为我们试图从多部分文件中多次读取inputstream。

    我曾经也遇到过这个问题,在我的例子中,首先我验证了文件的内容,然后我尝试在Spring多部分中使用“transferto”方法保存它。当我尝试使用“transferto”方法时,会出现这个异常。这里我要两次输入流。

    当文件太小时,我不会面临这个问题。在“transferto”方法中,存在对“isavailable”方法的内部调用。请遵循以下代码段:

        protected boolean More ...isAvailable() {
                // If in memory, it's available.
            if (this.fileItem.isInMemory()) {
                return true;
            }
            // Check actual existence of temporary file.
            if (this.fileItem instanceof DiskFileItem) {
                return ((DiskFileItem) this.fileItem).getStoreLocation().exists();
            }
            // Check whether current file size is different than original one.
            return (this.fileItem.getSize() == this.size);
        }
    

    链接: http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-web/3.2.1.RELEASE/org/springframework/web/multipart/commons/CommonsMultipartFile.java#CommonsMultipartFile.isAvailable%28%29

    观察:

    1. 如果文件太小,Spring会将其保存在内存中,当我们请求文件时,它会从内存中检索。我们可以多次请求它,因为文件在内存中。

    2. 如果它足够大,Spring会将其保存为一个临时文件,我们不知道该文件的位置,但在我们读取了inputstream之后,该文件可能会被Spring内部删除。然后,当我们第二次请求时,错误显示“不能再读取”。

    所以我的解决方案是首先,我必须使用“transferto”方法将它保存在服务器中,然后检索本地文件以进行验证或任何其他第二次需要的操作。

    我认为在“multipartresolver”bean中增加“maxuploadsize”是不好的,因为如果文件太大,它会消耗更多的内存。