the request was rejected because no multipart boundary was found

文章目录

  • [1. 需求描述](#1. 需求描述)
  • [2. 报错信息](#2. 报错信息)
  • [3. 探索过程](#3. 探索过程)
    • [1. 使用postman 排除后端错误](#1. 使用postman 排除后端错误)
    • [2. 搜索网上的解决方法](#2. 搜索网上的解决方法)
    • [3. 解决方法](#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");
        }
    }

如此该问题得到解决

相关推荐
咩咩啃树皮2 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚2 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白4 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司4 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地5 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun3141596 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风8 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
隔窗听雨眠8 小时前
Spring Boot在云原生时代的编程范式革新研究
spring boot·后端·云原生
z123456789869 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin5211239 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python