当前位置: 首页 > article >正文

the request was rejected because no multipart boundary was found

文章目录
  • 1. 需求描述
  • 2. 报错信息
  • 3. 探索过程
    • 1. 使用postman 排除后端错误
    • 2. 搜索网上的解决方法
    • 3. 解决方法

1. 需求描述

想要在前端上传一个PDF 发票,经过后端解析PDF之后,将想要的值自动回填到对应的输入框中

2. 报错信息

org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
	at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.init(FileItemIteratorImpl.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.getMultiPartStream(FileItemIteratorImpl.java:205) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.findNextItem(FileItemIteratorImpl.java:224) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.<init>(FileItemIteratorImpl.java:142) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:252) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:276) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.connector.Request.parseParts(Request.java:2932) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.connector.Request.getParts(Request.java:2834) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:95) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:88) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:122) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1209) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1043) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:696) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:779) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.68.jar:9.0.68]
	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_321]

3. 探索过程

1. 使用postman 排除后端错误

使用postman做接口测试,上传文件确实能够返回正确的值,可以确定是前端代码的问题
在这里插入图片描述
我的前端代码

<template>
  <div>
    <input type="file" @change="onFileChange" accept="application/pdf" />
    <button @click="uploadAndFillData" enctype="multipart/form-data">上传并回填数据</button>
    <!-- <vxe-button size="mini" status="primary" style="height:25px; margin: 0 0 2px 15px;" @click="uploadAndFillData">导入</vxe-button> -->
    <!-- 表单或区域来显示回填的数据 -->
    <div v-if="formData">
      <!-- 使用formData来显示或更新UI -->
      <!-- <p>数据: {{ formData.someKey }}</p>  -->
      <!-- 如果数据是只读的,可以这样显示 -->
      <div>
        <p><strong>发票号码:</strong> {{ formData.number }}</p>
        <p><strong>开票日期:</strong> {{ formData.date }}</p>
        <p><strong>总金额:</strong> {{ formData.amount }}</p>
        <p><strong>备注:</strong> {{ formData.remarks }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios';  
export default {
  data() {
    return {
      selectedFile: null,
      formData: null, // 用于存储从后端返回的数据
    };
  },
  methods: {
    onFileChange(e) {
      this.selectedFile = e.target.files[0];
    },

    uploadAndFillData() {
      // 检查文件是否已经选择
      if (!this.selectedFile) {
        alert("请先选择一个文件!");
        return;
      }

      const formData = new FormData(); // 创建一个FormData 对象,用于构建将要发送的数据
      formData.append("file", this.selectedFile); // 将文件添加到FormData中,字段名为file

      this.$http({
            url: `/api/invoice/upload`,
            method: 'post',
            data: formData,
            headers: {
              'Content-Type': 'multipart/form-data'
              // 'Content-Type': 'application/json'
            },
            // enctype:"multipart/form-data",
          })
      .then((response) => {
          this.formData = response.data; // 将解析后的数据保存到formData中
        }).catch((error) => {
          console.error("Error uploading file:", error);
          alert("上传文件时发生错误!");
        });
    },
  },
};
</script>

2. 搜索网上的解决方法

网上的方法很多,但是都没有能够解决我的问题

  1. 注释掉header中的content-type,直接404
  2. 使用axios也是 404
  3. 在application.yml 中添加文件大小的限制配置【500,还是报原错误】

3. 解决方法

求助于GPT检查前端页面的代码,GPT给出的说法如下,我确实是没有通过Vue插件方式配置axios,所以肯定不能使用this.$http , 顾改用axios的方式向后端发请求,但是之前说了会报错404,猜测可能是因为反向代理配置问题,导致前端并没有通过这个地址请求到后端,所以采用粗暴的方法,直接将后端地址写在axios的url中,并在controller上配置注解@CrossOrigin
在这里插入图片描述
修改后的前端代码

<template>
  <div>
    <input type="file" @change="onFileChange" accept="application/pdf" />
    <button @click="uploadAndFillData" enctype="multipart/form-data">上传并回填数据</button>
    <!-- <vxe-button size="mini" status="primary" style="height:25px; margin: 0 0 2px 15px;" @click="uploadAndFillData">导入</vxe-button> -->
    <!-- 表单或区域来显示回填的数据 -->
    <div v-if="formData">
      <!-- 使用formData来显示或更新UI -->
      <!-- <p>数据: {{ formData.someKey }}</p>  -->
      <!-- 如果数据是只读的,可以这样显示 -->
      <div>
        
        <p><strong>发票号码:</strong> {{ formData.number }}</p>
        <p><strong>开票日期:</strong> {{ formData.date }}</p>
        <p><strong>总金额:</strong> {{ formData.totalAmount }}</p>
        <p><strong>备注:</strong> {{ formData.note }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios';  
export default {
  data() {
    return {
      selectedFile: null,
      formData: null, // 用于存储从后端返回的数据
    };
  },
  methods: {
    onFileChange(e) {
      this.selectedFile = e.target.files[0];
    },

    uploadAndFillData() {
      // 检查文件是否已经选择
      if (!this.selectedFile) {
        alert("请先选择一个文件!");
        return;
      }

      const formData = new FormData(); // 创建一个FormData 对象,用于构建将要发送的数据
      formData.append("file", this.selectedFile); // 将文件添加到FormData中,字段名为file

      // this.$http({
      //       url: `/api/invoice/upload`,
      //       method: 'post',
      //       data: formData,
      //       headers: {
      //         'Content-Type': 'multipart/form-data'
      //         // 'Content-Type': 'application/json'
      //       },
      //       // enctype:"multipart/form-data",
      //     })

      axios.post('http://localhost:8080/invoice/upload', formData, {  
        headers: {  
          'Content-Type': 'multipart/form-data'  
        }  
      })  
      .then((response) => {
          this.formData = response.data; // 将解析后的数据保存到formData中
        }).catch((error) => {
          console.error("Error uploading file:", error);
          alert("上传文件时发生错误!");
        });
    },
  },
};
</script>

controller层中注解的配置

@CrossOrigin(origins = "http://localhost:8081", allowedHeaders = "*", allowCredentials = "true")
    @PostMapping("/upload")
    public ResponseEntity<Object> uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            // 调用你的文件解析服务
            InvoiceSubset parsedData = invoiceService.parsePdfFile(file);

            // 返回解析后的数据
            return ResponseEntity.ok(parsedData);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error parsing file");
        }
    }

如此该问题得到解决


http://www.kler.cn/a/465087.html

相关文章:

  • 你喜欢看哪类的网上视频教程?
  • Redis(二)value 的五种常见数据类型简述
  • 景区自助售卡机与定点酒店的合作双赢之策-景区酒店方案
  • RAG实战:本地部署ragflow+ollama(linux)
  • ES_如何设置ElasticSearch 8.0版本的匿名访问以及https_http模式的互相切换
  • MATLAB画柱状图
  • 【深度学习】卷积网络代码实战ResNet
  • Redission看门狗实现redis定期续期原理
  • CDGA|浅析自动化对数据治理的深远影响
  • 基于MPPT算法的光伏并网发电系统simulink建模与仿真
  • S2-016-RCE(CVE-2013-2251)--vulhub
  • SSM-Spring-IOC/DI注解开发
  • git@github.com:username/repository.git 报错:no such file or directory
  • 代码随想录算法训练营第49期总结
  • 从低通滤波器到高通滤波器及小波函数的构造-附Matlab源程序
  • k8s基础(3)—Kubernetes-Deployment
  • 数据挖掘——模型的评价
  • 机器学习 学习知识点
  • 比ftp好用的大文件传输方案
  • 纵览!报表控件 Stimulsoft Reports、Dashboards 和 Forms 2025.1 新版本发布!
  • 复习打卡大数据篇——HIVE 01
  • Elasticsearch名词解释
  • 基于深度学习的视觉检测小项目(三) 通过设计一个简单的用户界面设计了解pyside的基本套路
  • C# 设计模式(结构型模式):适配器模式
  • Redis 入门与实战指南
  • 自动化测试之Pytest框架(万字详解)