【问题标题】:jQuery and Spring-Boot file upload causes "Required request part 'file' is not present"jQuery 和 Spring-Boot 文件上传导致“所需的请求部分‘文件’不存在”
【发布时间】:2017-02-09 15:52:09
【问题描述】:

我有一个文件要上传到我的 spring-boot 微服务。我正在使用 jQuery 使用 FormData javascript 对象发布文件。由于无法将我的 FormData 文件与 RequestParam 文件匹配,Spring-boot 没有在我的控制器中调用我的端点。

JavaScript:

var name = "TEST";
var kml = '<kml><Document><Placemark id="' + name + '"><Point><coordinates>-69.83701518,47.817278750000014</coordinates></Point></Placemark></Document></kml>';
// upload the kml file to the server
var data = new FormData();
data.append('file', kml);
$.ajax({
    method: "POST",
    url: "http://localhost:9096/upload/" + name,
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    success: function(data){
        console.log("success", name, data);
    }
});

这是我的控制器代码:

@RestController
public class MicroServiceController {

    private Logger logger = LoggerFactory.getLogger(MicroServiceController.class);

    @RequestMapping(value="/upload/{name}", method = { RequestMethod.POST })
    public ResponseEntity<?> uploadKML(@PathVariable String name, @RequestParam("file") MultipartFile file ) throws IOException {
        logger.debug("Upload: {}", name);

        return new ResponseEntity<Boolean>(true, HttpStatus.OK);
    }
}

这是一个例外:

2017-02-09 11:45:52.860 DEBUG 5521 --- [nio-9096-exec-1] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'microServiceController'
2017-02-09 11:45:52.888 DEBUG 5521 --- [nio-9096-exec-1] .w.s.m.m.a.ServletInvocableHandlerMethod : Failed to resolve argument 1 of type 'org.springframework.web.multipart.MultipartFile'

org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
    at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:193) ~[spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109) ~[spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.6.RELEASE.jar!/:4.3.6.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

2017-02-09 11:45:52.889 DEBUG 5521 --- [nio-9096-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<?> com.jasco.microservice.MicroServiceController.uploadKML(java.lang.String,org.springframework.web.multipart.MultipartFile) throws java.io.IOException]: org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
2017-02-09 11:45:52.891 DEBUG 5521 --- [nio-9096-exec-1] .w.s.m.a.ResponseStatusExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<?> com.jasco.microservice.MicroServiceController.uploadKML(java.lang.String,org.springframework.web.multipart.MultipartFile) throws java.io.IOException]: org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
2017-02-09 11:45:52.891 DEBUG 5521 --- [nio-9096-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<?> com.jasco.microservice.MicroServiceController.uploadKML(java.lang.String,org.springframework.web.multipart.MultipartFile) throws java.io.IOException]: org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
2017-02-09 11:45:52.891 DEBUG 5521 --- [nio-9096-exec-1] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-02-09 11:45:52.892 DEBUG 5521 --- [nio-9096-exec-1] o.s.web.servlet.DispatcherServlet        : Successfully completed request

这是请求和标头:

Request URL:http://localhost:9096/upload/TEST
Request Method:POST
Status Code:400 
Remote Address:127.0.0.1:9096

Request Headers:
  Accept:*/*
  Accept-Encoding:gzip, deflate, br
  Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
  Cache-Control:no-cache
  Connection:keep-alive
  Content-Length:273
  Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryM401einBJzuTMVSj
  Host:localhost:9096
  Origin:http://localhost:8090
  Pragma:no-cache
  Referer:http://localhost:8090/
  User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36

Request Payload
------WebKitFormBoundaryM401einBJzuTMVSj
Content-Disposition: form-data; name="file"

<kml><Document><Placemark id="TEST"><Point><coordinates>-69.83701518,47.817278750000014</coordinates></Point></Placemark></Document></kml>
------WebKitFormBoundaryM401einBJzuTMVSj--

以及响应 JSON:

{"timestamp":1486655346223,"status":400,"error":"Bad Request","exception":"org.springframework.web.multipart.support.MissingServletRequestPartException","message":"Required request part 'file' is not present","path":"/upload/TEST"}

对我来说,看起来我将文件名设置为“文件”,并且我也在微服务中寻找“文件”......但它似乎没有在 spring 上建立连接-引导端。我很困惑,因为这一切看起来都像我在互联网上找到的示例和问题,但我仍然得到例外。

任何关于下一步要尝试什么或我搞砸的地方的建议都会很有帮助!

【问题讨论】:

  • 我对 spring-boot 社区取消他们的论坛,然后不回答 stackoverflow 问题感到非常失望。他们网站上几乎整个问题页面都有 0 个答案。
  • 对于其他遇到此问题的人,我正在通过不使用表单数据而是将 kml 放入正文中来解决此问题,然后将参数从“@RequestParam MultipartFile 文件”更改为“@ RequestBody 字符串 kml”。如果我的公里数太大,我会被狗咬的。
  • 我发现把MultipartFile改成MultipartFile[]会调用成功,但是数组是空的。
  • 底层请求包含正确的上传文件数据,但spring-boot无法识别。不确定这是弹簧启动错误还是我做错了什么 - 我不会解决这个问题 - 只是通过使用 body raw 来避开它。

标签: jquery spring spring-boot file-upload netflix-zuul


【解决方案1】:

原来这是系统架构和 Netflix 造成的问题。正在使用zuul重定向请求,有an issue in Zuul that is causing the name of the MultiPart form parameter to be stripped

我正在升级到 Spring Boot 2.1 - 我认为它应该可以修复它。

【讨论】:

    【解决方案2】:

    您在控制器方法中使用 @RequestParam("file"),因此控制器希望您的 file 值包含在请求中,例如:

    http://localhost:9096/upload/TEST?file=TEST
    

    如果您不想将文件参数作为 URL 的一部分发送,您应该尝试使用不同的 Spring 注解,例如 @ModelAttribute

    希望对你有帮助,

    【讨论】:

    • 我看到的所有分段文件上传示例都使用@RequestParam 作为文件。我会更仔细地研究它,因为它是有道理的。
    • 显然,文件上传与将对象嵌入到请求正文中的工作方式不同。还是没有成功。
    猜你喜欢
    • 2017-04-06
    • 2019-09-08
    • 1970-01-01
    • 2017-10-09
    • 2020-10-22
    • 1970-01-01
    • 2017-10-11
    • 2020-09-14
    相关资源
    最近更新 更多