Spring FileUpload的问题

时间:2010-09-19 20:53:29

标签: java spring file-upload spring-mvc

我有以下代码块处理我在Spring MVC Web应用程序中使用的照片的文件上传。我使用Spring MVC CommonsMultipartFileResolver来处理文件上传。

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文件中,我有以下代码来配置MultipartFile解析器bean。

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

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

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

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)

我尝试了一些配置Multipart解析器的不同选项,例如将其切换为处理 CommonsMultipartFile 对象,而不是普通的 MultipartFile 对象,但没有任何改变。< / p>

我还尝试使用以下属性在CommonsMultipartFileResolver bean中配置最大上载大小。

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

也没有改变。我不确定CommonsMultipartResolver默认为可以上传的文件大小,但这不是我的问题。

我被告知我遇到的问题是由于Spring正在使用的Multipart解析器/处理程序中的问题。我最近有一篇关于同样问题的帖子,并且由于发现了新信息,因此希望重新发布新信息。可以在CommonsMultipartFileResolver Problem

找到旧帖子

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

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

修改的 注意 - 我一直在尝试上传不同尺寸的照片,我相信它允许我上传的限制大约是10Kb。任何大于10Kb的东西都会导致它破裂并给我上面的错误。

3 个答案:

答案 0 :(得分:12)

经过大量研究,我解决了我的问题。事实证明,没有为使用 CommonsMultipartFileResolver 上传的最大字节数设置默认限制。当然,您可以通过设置以下属性在bean中指定您想要的任何数量。

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

还有一个属性 maxInMemorySize ,允许您指定在将文件写入磁盘之前允许的最大大小。虽然这与最大上载大小的工作方式相同,但如果未指定数量,则默认为1024字节。如果我尝试上传大文件,这可以解释它。

为了允许上传1024字节以上的文件,您需要将maxInMemorySize值增加到您需要的任何值,如下所示...     

这就是照顾我的问题。我在查看CommonsFileUpload文档的文档时了解到这个属性默认为1024。

您可以在CommonsFileUpload Documentation

查看此文档

我希望这对任何人都有帮助,因为没有关于使用CommonsMultipartFile的非常好的文档。

答案 1 :(得分:3)

我注意到只有当文件超过1024字节并且您尝试读取文件两次时才会出现此错误。正如CitadelCSAlum所提到的,设置maxInMemorySize = maxUploadSize将解决这个问题,但是应该记住内存使用情况。如果考虑内存,另一个选择是在第一次读取时将多部分文件数据写入临时文件,并使用该文件进行后续读取。如果您没有阅读两次,则不需要增加maxInMemorySize。

答案 2 :(得分:2)

您在问题中引用的例外情况说明:&#34;文件已被移动 - 无法再次阅读&#34;。这是因为我们试图从multipart文件中多次读取输入流。

我也同时遇到过这个问题,在我的情况下,首先我验证了文件的内容,之后我尝试使用&#34; transferTo&#34; Spring MultiPart中的方法。当我尝试使用&#34; transferTo&#34;方法。在这里,我要求输入两次。

当文件太小时,我不会遇到此问题。在&#34; transferTo&#34;方法有一个内部调用&#34; isAvailable&#34;方法。请按照以下代码段进行操作:

    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);
    }

link: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. 如果它太小,弹簧将它保存在内存中,当我们要求文件时,它会从内存中恢复。我们可以多次要求它,因为文件在内存中。

  2. 如果它足够大,Spring会将它保存为我们不知道位置的临时文件,但是在我们读取inputstream之后,一旦该文件可能被Spring内部删除。然后,当我们第二次要求错误表示&#34;无法再次阅读&#34;。

  3. 所以我的解决方案首先是我必须使用&#34; transferTo&#34;将其保存在服务器端口中。方法并检索要验证的本地文件或任何其他第二次需要的文件。

    我认为增加&#34; maxUploadSize&#34; in&#34; multipartResolver&#34;如果文件太大,它会消耗更多的内存。