Advertisement

根据源码用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

其实工作经常遇到这类情况,在工作中经常会遇到这种情况;但事实上那些看似遥远的地方往往就是通往目标的捷径

转载于:https://www.cnblogs.com/wangxin37/p/6398717.html

全部评论 (0)

还没有任何评论哟~