根据源码用HttpServletRequest获取MultipartFile的问题
发布时间
阅读量:
阅读量
问题
鉴于某种需求
按常规写法,photoFile参数的required配置设置为了false。
在调试过程中发现,在config中photoFile标记为required后却不起作用。具体来说,在下面接口实现中,其中必须传递 photoFile参数。
@ResponseBody
@RequestMapping(value = "/upload")
public String uploadPics(@RequestPart(value = "photoFile", required = false) MultipartFile photoFile,
@RequestParam(value = "type", required = true) String type, HttpServletRequest request) throws Exception {
。。。
}
在模拟上传接口请求的过程中,请注意如果未携带 photoFile 参数,则该上传接口书写方式将导致错误出现
org.springframework.web.multipart.MultipartException: The current request is not a multipart request
at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.assertIsMultipartRequest(RequestPartMethodArgumentResolver.java:178) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.resolveArgument(RequestPartMethodArgumentResolver.java:116) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:79) ~[spring-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157) ~[spring-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124) ~[spring-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945) ~[spring-webmvc-4.0.2.RELEASE.jar:4.0.2.RELEASE]
...
方案
若required配置出现故障,则可能表明未执行相关流程。
111 @Override
112 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
113 NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {
114
115 HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
116 assertIsMultipartRequest(servletRequest);
117
118 MultipartHttpServletRequest multipartRequest =
119 WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
120
121 String partName = getPartName(parameter);
122 Object arg;
123
124 if (MultipartFile.class.equals(parameter.getParameterType())) {
125 Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
126 arg = multipartRequest.getFile(partName);
}
.....
再点击116行,进入assertIsMultipartRequest方法
175 private static void assertIsMultipartRequest(HttpServletRequest request) {
176 String contentType = request.getContentType();
177 if (contentType == null || !contentType.toLowerCase().startsWith("multipart/")) {
178 throw new MultipartException("The current request is not a multipart request");
179 }
}
不言而喻的是,在第178行发生了错误。值得注意的是,在上层几个调用中并未涉及required流程。
值得商榷的是,在接口偶尔需承担上传职责的情况下,默认无法修改传参形式就必须重构源码。显然这并非理想解决方案。
答案自然藏在源码中了。我们容易就能想到,在接口处完全去除photoFile(MultipartFile)参数,并将模拟源码从request中获取MultipartFile对象。
下面是根据源码118-126行、176-179行修改的接口,经测试是可行的:
@ResponseBody
@RequestMapping(value = "/upload")
public String uploadPics(@RequestParam(value = "type", required = true) String type,
HttpServletRequest request) {
....
// 检测是否为上传请求
String contentType = request.getContentType();
if (contentType != null && contentType.toLowerCase().startsWith("multipart/")) {
MultipartHttpServletRequest multipartRequest =
WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
MultipartFile file = multipartRequest.getFile("file");
....
}
....
}
后记
问题的处理其实很简单,但是这边文章的记录是为了另一件事。
在试图完成这一功能的过程中, 发现传统的编码方式行不通, 不好修改源代码, 其内心思绪如潮水般翻涌.
答案很可能藏在源代码中。猜测可以通过request手段获取到MultipartFile对象,但这样操作起来却有些繁琐。实在不愿投入精力去做这件事。或许有更为简便的方法?这样一来事情就拖延了下来。
向同事询问解决问题的方法后得知,建议可以从request中获取MultipartFile对象哦。:-O
其实工作经常遇到这类情况,在工作中经常会遇到这种情况;但事实上那些看似遥远的地方往往就是通往目标的捷径
全部评论 (0)
还没有任何评论哟~
