java.lang.IllegalStateException: File has already been moved - cannot be transferred again

12,692

Solution 1

The exception you reference in your question states: "File has been moved - cannot be read again". This is because we are trying to read inputstream more than one time from multipart file.

I also faced this issue at one time, and in my case, first I validated the content of the file, and after that I tried to save it using "transferTo" method in Spring MultiPart. This exception comes when I try to use "transferTo" method. Here I am calling for inputstream twice.

I do not face this issue when file size is too small. In "transferTo" method there is an internal call for "isAvailable" method. Please follow the code segment below:

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

Observations:

If it is too small, spring save it in memory and when we ask for the file it retrive from memory. We can ask for it multiple times because file is in memory.

If it is large enough, Spring will save it as a temporary file which we do not know the location, but after we read inputstream once that file may be deleted internally by Spring. Then when we ask for the second time that error says "cannot be read again".

So my solution is first I have to save it in server loaction using "transferTo" method and retrive that local file to validate or any other second time need.

I think it is not good to increase "maxUploadSize" in "multipartResolver" bean as it consumes more memory if the file is too large.

Solution 2

It seems that the file is not available as a temporary file (e.g).

Just having a look at the code of transferTo() method and calling isAvailable method which throws your exception:

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

In other cases this exception will not be thrown.

Share:
12,692

Related videos on Youtube

Xavier DSouza
Author by

Xavier DSouza

Bachelor in Computers

Updated on June 04, 2022

Comments

  • Xavier DSouza
    Xavier DSouza almost 2 years

    I am trying to upload a file and save it on server. But I get:

    java.lang.IllegalStateException: File has already been moved - cannot be transferred again
    

    I am using Commons FileUpload jar(CommonsMultipartFile). I get IllegalStateException for statement : user.getFileData().transferTo(new File("/home/xavier/uploads/" + user.getFileData().getOriginalFilename()));

    Here user is the bean. It worked for me initially but when I tested again by deleting the files from uploads folder it threw exception as above.

    Stacktrace:

    java.lang.IllegalStateException: File has already been moved - cannot be transferred again
        at org.springframework.web.multipart.commons.CommonsMultipartFile.transferTo(CommonsMultipartFile.java:126)
        at com.raistudies.controllers.RegistrationController.processForm(RegistrationController.java:113)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
        at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
        at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
        at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
        at java.lang.Thread.run(Thread.java:722)
    
    • AllTooSir
      AllTooSir about 11 years
      This is caused by either 1) calling multipartFile.transferTo(destFile) more then once, or 2) calling transferTo outside of the request lifecycle.
    • Xavier DSouza
      Xavier DSouza about 11 years
      I solved my problem. Here is the link stackoverflow.com/questions/3747430/…
  • Dennis Meng
    Dennis Meng almost 10 years
    You might want to change the formatting; it's hard to read if you format non-code as code. The last part is also cut off; was there something else you were trying to say?
  • Arosha
    Arosha almost 10 years
    I formatted my answer. Please do reply any concerns.
  • Ursache
    Ursache over 4 years
    Thank you for the help! This was the solution in my case.