arrrrrrrrrrrrrrgh

Friday, February 6, 2009

Spring MultipartFile transferTo error


java.lang.IllegalStateException: File has already been moved - cannot be transferred again
at org.springframework.web.multipart.commons.CommonsMultipartFile.transferTo(CommonsMultipartFile.java:128)



If you are using Spring MVC, this is caused by either 1) calling multipartFile.transferTo(destFile) more then once, or 2) calling transferTo outside of the request lifecycle.

It seems the multipartFile is only valid within the confines of the request it was posted in. If you save it in session and attempt to use it later, or process it in a separate thread, the multipartFile will no longer be valid.

Wednesday, October 8, 2008

Spring MVC, Multiple/Arbitrary Number of File Uploads

Handle an arbitrary number of file uploads in a single form submission. This assumes you are using some javascript on your page to create new file upload form elements as your user requests them (like the add attachment button in gmail).

Using Spring's normal command bean binding or annotated method way of doing things requires you to know exactly the number of file uploads you expect at compile time.

Using Spring MVC 2.5:

@RequestMapping("/uploadFiles")
public String uploadFiles(HttpServletRequest request) {
if (request instanceof AbstractMultipartHttpServletRequest == false) {
throw new RuntimeException("Did not recieve an instance of AbstractMultipartHttpServletRequest.");
}
Map<String, MultipartFile> paramToFileMap = ((AbstractMultipartHttpServletRequest) request).getFileMap();
for (String fileParameter : paramToFileMap.keySet()) {
MultipartFile file = paramToFileMap.get(fileParameter);
// do something here...

}
return "uploadSuccess";
}

Spring MVC 2.5, Annotations, Controller, MultipartFile

Hello search-engine user,

The exception you experienced...


org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.multipart.MultipartFile]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:75)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:357)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:201)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:128)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:310)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:292)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:613)


... is caused by not annotating your method parameter with @RequestParam.


@RequestMapping("/uploadFile", method=RequestMethod.POST)
public String uploadFile(@RequestParam(value="myFile", required=true) MultipartFile file) {
...
}

Since spring does not know what upload parameter goes with MultipartFile without the annotation, it attempts to create a new default instance of the parameter to pass in. It can't do that for an interface, hence the error message.