1 堆栈信息

老规矩,先贴出堆栈信息,可以看到最终的保存信息为:org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present

org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
	at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.resolveArgument(RequestPartMethodArgumentResolver.java:154)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.github.xiaoymin.swaggerbootstrapui.filter.SecurityBasicAuthFilter.doFilter(SecurityBasicAuthFilter.java:84)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.github.xiaoymin.swaggerbootstrapui.filter.ProductionSecurityFilter.doFilter(ProductionSecurityFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.cloud.sleuth.instrument.web.TraceFilter.doFilter(TraceFilter.java:153)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)
2 后端代码
2.1文件上传依赖
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
2.2 controller层代码

由于还没进入到controller内部就已经报错了,故后端代码贴到这里就可以了

    @PostMapping(value = "/importAccidentInfo")
    @ApiOperation(value = "导入事故信息")
    public ReturnDTO importAccidentInfo(@RequestPart(value = "file") MultipartFile file) throws Exception {
        if (file == null) {
            return ReturnDTO.fail("文件为空,请上传文件");
        }
        List<AccidentInfoVO> accidentInfoVOS = PoiUtils.importExcel(file, AccidentInfoVO.class);
        if (!CollectionUtils.isEmpty(accidentInfoVOS)) {
            ReturnDTO returnDTO = dictionaryService.setAccidentTypeInfo(accidentInfoVOS);
            ReturnDTO returnDTO2=dictionaryService.setAccidentLicense(accidentInfoVOS);
            if(returnDTO.izSuccess()&&returnDTO2.izSuccess()){
                List<PcmsAccidentInfo> collect = accidentInfoVOS.stream().map(item -> {
                    PcmsAccidentInfo pcmsAccidentInfo = new PcmsAccidentInfo();
                    BeanUtils.copyProperties(item, pcmsAccidentInfo);
                    return pcmsAccidentInfo;
                }).collect(Collectors.toList());
                accidentInfoService.batchSave(collect);
                return ReturnDTO.success("上传成功", null);
            }else {
                return ReturnDTO.fail(returnDTO.getReturnMsg());
            }
        }
        return ReturnDTO.fail("上传文件无可用数据", null);
    }
3 前端代码

vue项目使用的是element-ui组件el-upload

          <el-upload
            action
            :show-file-list="false"
            :auto-upload="false"
            :before-upload="beforeUpload"
            :on-change="uploadFile"
            style="display: inline-block;"
          >
            <Button icon="ios-download" type="primary">导入</Button>
          </el-upload>

方法代码:使用手动提交方式,利用封装的axios进行文件上传

      beforeUpload(file) {
        console.log(file);
      },
      //导入信息
      uploadFile(file) {
        let _this = this;
        let fileName = file.name;
        let suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        console.log(file);
        if (suffix != "xls" && suffix != "xlsx") {
          _this.$Message.error("导入文件格式错误!请正确导入电子表格");
          return;
        }
        let formData = new FormData();
        formData.append("file", file);
        try {
          this.$ajax({
            method: "post",
            url:
            sessionStorage.getItem("zuul") +
            this.$store.state.pcmsService +
            "/accidentInfo/importAccidentInfo",
            //   headers: {
            //     "Content-Type": "application/json;charset=UTF-8"
            //   },
            data: formData
          }).then(res => {
            if (res.data.returnCode != 0) {
              this.$Message.error(res.data.returnMsg || "数据上传失败!");
              return;
            }
            //   this.tableData = [...res.data.data.rows];
          });
        } catch (error) {
          console.error(error);
          let Msg = (error && error.message) || "";
          this.$Message.error(Msg || "数据上传失败!");
        }
      },

请求信息如下图:

  1. 响应码为200,说明URL无误,且已经与后台正常通信
  2. 参数名称为file
  3. 提交方式为:formData
    在这里插入图片描述
4 解决方案

以下是我从别人博客搜到的解决方案,都没用,不过也贴出来吧,也许对你们其中某些人有用

  1. File名称不一致:网上大多数帖子都说是文件的name与后端@RequestParam(或@RequestPart)的value不一致,稍微搜一搜,十篇有八篇写的这玩意.然而,如上所见我的参数名称没什么问题.
  2. 后端缺少文件上传的配置:这个更扯淡了,因为springboot自动配置中,文件上传就是打开的,也就是这个配置:spring.http.multipart.enabled=true
  3. springboot自动配置与xml配置冲突:项目没有配置xml,更不存在自定义文件处理器的bean覆盖springboot默认配置
  4. PostMapping注解配置comsumers:亲测无效
  5. @RequestParam改为@RequestPart:这个我就很纳闷,那我以前做这个功能一直都用@RequestParam怎么不报错??

好了,经过以上折腾.我觉得我该冷静一下,仔细分析分析.
接下来,我使用Postman发送了一个文件.嗯??竟然可以成功??至此,我可以假定后端程序没有问题.
在这里插入图片描述
接下来就是分析前端代码,首先检查一下文件是不是真的上传了,经过验证,进入upload方法的file的的确确存在.我把它打印到控制台,方便大家观察.
在这里插入图片描述
其实到这里,我就已经感觉有点不大对劲.后台接收的文件应该是一个二进制流才对,这个file对象的内容似乎过于庞大.于是我将file改为了file.raw,也就是下图的模样
在这里插入图片描述
经测试,文件可以正常上传.大家可以观察一下请求有什么不一样的地方
在这里插入图片描述
没错,formData里面多了文件的信息,像fileName等等

5 总结

当出现Required request part ‘file’ is not present错误,可以检查一下请求中是否真的存在文件.像vue上传组件,实际的file应该是file.raw

检查错误不容易,能帮到你们的话,请给我个赞…

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐