Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring's support for javax.servlet.http.Part vs. MultipartFile incomplete, inconsistent [SPR-10591] #15220

Closed
spring-projects-issues opened this issue May 27, 2013 · 2 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented May 27, 2013

Nick Williams opened SPR-10591 and commented

Spring's support for javax.servlet.http.Part vs. org.springframework.web.multipart.MultipartFile is very inconsistent. You cannot use the two the same ways, which the documentation seems to suggest should be the case.

I'm using @Configuration with @EnableWebMVC. I define the following bean in my configuration:

@Bean
public MultipartResolver multipartResolver()
{
    return new StandardServletMultipartResolver();
}

The following eight scenarios demonstrate the inconsistencies. It seems to me that all eight scenarios should work, but three of them do not.

Scenario 1

I have a controller handler method with a @RequestPart MultipartFile parameter. Everything works fine, and when the method is called the uploaded file is supplied to the method.

Scenario 2

I have a controller handler method with a @RequestPart List<MultipartFile> parameter. Everything works fine, and when the method is called the uploaded file or files are supplied to the method (I tired uploading a single file and multiple files; both worked).

Scenario 3

I have a controller handler method with a @RequestPart Part parameter. Everything works fine, and when the method is called the uploaded file is supplied to the method.

Scenario 4

I have a controller handler method with a @RequestPart List<Part> parameter. I tired uploading a single file and multiple files, but neither worked. Spring replied to the request with error code 415: "The server refused this request because the request entity is in a format not supported by the requested resource for the requested method." The following debug information appeared in the log for this request:

13:17:07.352 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:823): DispatcherServlet with name 'springDispatcher' processing POST request for [/support/ticket/create]
13:17:07.376 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:222): Looking up handler method for path /ticket/create
13:17:07.376 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:229): Returning handler method [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form,java.util.List<javax.servlet.http.Part>) throws java.io.IOException]
13:17:07.376 [http-nio-8080-exec-3] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:249): Returning cached instance of singleton bean 'ticketController'
13:17:07.561 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form,java.util.List<javax.servlet.http.Part>) throws java.io.IOException]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported
13:17:07.565 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form,java.util.List<javax.servlet.http.Part>) throws java.io.IOException]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported
13:17:07.566 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form,java.util.List<javax.servlet.http.Part>) throws java.io.IOException]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported
13:17:07.567 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:999): Null ModelAndView returned to DispatcherServlet with name 'springDispatcher': assuming HandlerAdapter completed request handling
13:17:07.567 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:976): Successfully completed request

Scenario 5

I have a controller handler method with a Form command-object parameter. The Form (POJO) has a field in it of type MultipartFile. Everything works fine, and when the method is called the uploaded file is supplied to the method.

Scenario 6

I have a controller handler method with a Form command-object parameter. The Form has a field in it of type List<MultipartFile>. Everything works fine, and when the method is called the uploaded file or files are supplied to the method (I tired uploading a single file and multiple files; both worked).

Scenario 7

I have a controller handler method with a Form command-object parameter. The Form (POJO) has a field in it of type Part. I cannot upload a file. Spring replied to the request with error code 400: "The request sent by the client was syntactically incorrect." The following debug information appeared in the log for this request:

13:37:27.657 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:823): DispatcherServlet with name 'springDispatcher' processing POST request for [/support/ticket/create]
13:37:27.685 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:222): Looking up handler method for path /ticket/create
13:37:27.686 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:229): Returning handler method [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]
13:37:27.686 [http-nio-8080-exec-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:249): Returning cached instance of singleton bean 'ticketController'
13:37:27.690 [http-nio-8080-exec-4] DEBUG org.springframework.beans.BeanUtils org.springframework.beans.BeanUtils.findEditorByConvention(BeanUtils.java:443): No property editor [javax.servlet.http.PartEditor] found for type javax.servlet.http.Part according to 'Editor' suffix convention
13:37:27.693 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'form' on field 'attachments': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@8e3de73]; codes [typeMismatch.form.attachments,typeMismatch.attachments,typeMismatch.javax.servlet.http.Part,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [form.attachments,attachments]; arguments []; default message [attachments]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'javax.servlet.http.Part' for property 'attachments'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [javax.servlet.http.Part] for property 'attachments': no matching editors or conversion strategy found]
13:37:27.696 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'form' on field 'attachments': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@8e3de73]; codes [typeMismatch.form.attachments,typeMismatch.attachments,typeMismatch.javax.servlet.http.Part,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [form.attachments,attachments]; arguments []; default message [attachments]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'javax.servlet.http.Part' for property 'attachments'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [javax.servlet.http.Part] for property 'attachments': no matching editors or conversion strategy found]
13:37:27.696 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'form' on field 'attachments': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@8e3de73]; codes [typeMismatch.form.attachments,typeMismatch.attachments,typeMismatch.javax.servlet.http.Part,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [form.attachments,attachments]; arguments []; default message [attachments]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'javax.servlet.http.Part' for property 'attachments'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [javax.servlet.http.Part] for property 'attachments': no matching editors or conversion strategy found]
13:37:27.700 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:999): Null ModelAndView returned to DispatcherServlet with name 'springDispatcher': assuming HandlerAdapter completed request handling
13:37:27.701 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:976): Successfully completed request

Scenario 7

I have a controller handler method with a Form command-object parameter. The Form (POJO) has a field in it of type List<Part>. I tired uploading a single file and multiple files, but neither worked. Spring replied to the request with error code 400: "The request sent by the client was syntactically incorrect." The following debug information appeared in the log for this request:

13:39:27.414 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:823): DispatcherServlet with name 'springDispatcher' processing POST request for [/support/ticket/create]
13:39:27.443 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:222): Looking up handler method for path /ticket/create
13:39:27.447 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:229): Returning handler method [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]
13:39:27.448 [http-nio-8080-exec-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:249): Returning cached instance of singleton bean 'ticketController'
13:39:27.488 [http-nio-8080-exec-1] DEBUG org.springframework.beans.BeanUtils org.springframework.beans.BeanUtils.findEditorByConvention(BeanUtils.java:443): No property editor [javax.servlet.http.PartEditor] found for type javax.servlet.http.Part according to 'Editor' suffix convention
13:39:27.491 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'form' on field 'attachments': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@3f7c6df8]; codes [typeMismatch.form.attachments,typeMismatch.attachments,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [form.attachments,attachments]; arguments []; default message [attachments]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.util.List' for property 'attachments'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [javax.servlet.http.Part] for property 'attachments[0]': no matching editors or conversion strategy found]
13:39:27.494 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'form' on field 'attachments': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@3f7c6df8]; codes [typeMismatch.form.attachments,typeMismatch.attachments,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [form.attachments,attachments]; arguments []; default message [attachments]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.util.List' for property 'attachments'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [javax.servlet.http.Part] for property 'attachments[0]': no matching editors or conversion strategy found]
13:39:27.494 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:134): Resolving exception from handler [public org.springframework.web.servlet.View com.wrox.site.TicketController.create(javax.servlet.http.HttpSession,com.wrox.site.TicketController$Form) throws java.io.IOException]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'form' on field 'attachments': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@3f7c6df8]; codes [typeMismatch.form.attachments,typeMismatch.attachments,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [form.attachments,attachments]; arguments []; default message [attachments]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.util.List' for property 'attachments'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [javax.servlet.http.Part] for property 'attachments[0]': no matching editors or conversion strategy found]
13:39:27.495 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:999): Null ModelAndView returned to DispatcherServlet with name 'springDispatcher': assuming HandlerAdapter completed request handling
13:39:27.496 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:976): Successfully completed request

Affects: 3.1 GA, 3.2 GA, 4.0 M1

Issue Links:

Referenced from: commits e91ce23, cc4faa5, 803779d

@spring-projects-issues
Copy link
Collaborator Author

Brian Clozel commented

a PR has been submitted; this should fix the last two scenarii listed in this issue.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

All scenarios should now work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants