场景:

在写一个统一文件上传的时候,MultipartFile参数一直传递不进来,一直为空。

排错方法:

我先是将业务简化,使用api文档进行测试,测试是前端问题还是后端问题。

简化后业务:

用apifox文档测试之后,还是显示报错

{
"code": 500,
"message": "Required part 'file' is not present.",
"result": null,
"type": "error"
}

代表其实servlet请求体里根本没有这个文件流参数,跟文件名和参数名没有太大关系,而且文件上传springboot是默认打开的,也不需要显示的去打开

  # 数据源配置
servlet:
multipart:
enabled: true
max-file-size: 20MB
max-request-size: 20MB

之后一直根据这个报错信息去查找相关文档,发现出现这个问题的有很多种原因,那就一个一个去排查

1.前后端参数名对应不一致
2.spring.servlet.multipart.enabled=false即关闭文件上传支持
3.配置文件中指定了文件上传时的大小值问题
4.切换内嵌容器tomcat到undertow的配置问题
5.spring.servlet.multipart.location=/tmp指定了临时文件站,但路径不存在
6.多次读取HttpServletRequest流
7.springboot已经有CommonsMultipartResolver,需要排除原有的Multipart配置@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})

一个个排查之后,发现自己在请求体到接口之前就被使用过多次,很符合多次读取HttpServletRequest流的问题

就是这里使用了:

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; /**
* CachedBodyHttpServletRequest 扩展了 HttpServletRequestWrapper 类,
* 用于缓存请求体,使其可以被多次读取。
*/
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper { private final byte[] cachedBody; /**
* 构造函数,读取请求体并进行缓存。
*
* @param request 原始的 HttpServletRequest
* @throws IOException 如果发生 I/O 错误
*/
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
super(request); // 读取请求体并将其转换为字节数组
InputStream requestInputStream = request.getInputStream();
this.cachedBody = requestInputStream.readAllBytes();
}
 
发现了问题,就好解决了,找到在哪里调用了这个请求体缓存,写这个缓存的目的也是为了解决请求体不能被多次使用的问题,因为我有一个自动检测验证码的拦截器需要去拦截登录接口的参数,
之前是方法没有注意,本来是不应该有这个错误的,第一个是没有正确在缓存里配置文件流的操作,第二个是验证码拦截器并没有针对登录接口专门做,而是都拦截了下来,导致都是用的这个缓存
 
之后就修改一下代码就好了,让这个拦截器只拦截登录接口的时候处理业务:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 检查请求 URL 和方法
String url = request.getRequestURI();
if ("/bt/login".equals(url) && request.getMethod().equals("POST")) {
// 包装请求,缓存请求体
CachedBodyHttpServletRequest cachedBodyHttpServletRequest = new CachedBodyHttpServletRequest(request);
try {
// 解析请求体
LoginUserDto loginUserDto = JSON.parseObject(cachedBodyHttpServletRequest.getReader(), LoginUserDto.class); // 验证码校验逻辑
if (loginUserDto.getCode() == null || !loginUserDto.getCode().equals(redisUtil.get(RedisKeys.CAPTCHA + loginUserDto.getUuid()))) {
throw new CaptchaException("验证码错误");
} // 验证码正确,删除验证码
redisUtil.del(RedisKeys.CAPTCHA + loginUserDto.getUuid());
} catch (CaptchaException e) {
// 交给认证失败处理器
loginFailureHandler.onAuthenticationFailure(cachedBodyHttpServletRequest, response, e);
return;
}
// 继续处理请求
filterChain.doFilter(cachedBodyHttpServletRequest, response);
}
filterChain.doFilter(request, response);
}
到此,顺利解决问题。
{
"code": 0,
"message": "操作成功",
"result": "url访问地址...",
"type": "success"
}
 

springboot 3.x MultipartFile 参数总是为空 参数传递不进来的更多相关文章

  1. springboot返回数据null参数设为空字符串或空数组

    package com.ruoyi.framework.config.ResponseVoConfig.WebConfig; /** * @Classname MyJsonMapper * @Desc ...

  2. # SpringBoot使用Validation校验参数 ##

    SpringBoot使用Validation校验参数 一.简介 参考 (14条消息) 1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知_@decimalmax和@max_ ...

  3. 使用Jayrock开源组件创建参数可为空的接口

    经过上一篇文章对Jayrock开源组件的分析,我发现了一个问题,就是在写接口的时候,可以设置某个参数为空,可以不需要进行参数的传递,具体写法如下: 图上的test参数就是可空类型,只需标识为int?类 ...

  4. AOP实现参数的判空问题

    不想每次都去判断必传的参数是否为空,写代码太繁琐了,正好最近用了AOP实现权限控制,依葫芦画瓢,现在用它实现参数的判空,至于AOP的原理之类,自己百度了解一下吧 1. NullDisable注解 @D ...

  5. SpringBoot获取http请求参数的方法

    SpringBoot获取http请求参数的方法 原文:https://www.cnblogs.com/zhanglijun/p/9403483.html 有七种Java后台获取前端传来参数的方法,稍微 ...

  6. Asp.net webapi 判断请求参数是否为空简易方法 Model Validation 判断请求参数是否为空

    通常情况下,对于那些经常为别人提供数据接口的开发人员来说,对于调用方传递过来的参数都会有验证处理.例如: if (string.IsNullOrEmpty(entity.Name)) { //当姓名为 ...

  7. 【快学springboot】4.接口参数校验

    前言 在开发接口的时候,参数校验是必不可少的.参数的类型,长度等规则,在开发初期都应该由产品经理或者技术负责人等来约定.如果不对入参做校验,很有可能会因为一些不合法的参数而导致系统出现异常. 上一篇文 ...

  8. 使用AOP和Validator技术对项目接口中的参数进行非空等校验

    javax.validation.Validator基础知识补充: validator用来校验注解的生效,如: @NotBlank(message = "地址名不能为空") pri ...

  9. springBoot 过滤器去除请求参数前后空格(附源码)

    背景 : 用户在前端页面中不小心输入的前后空格,为了防止因为前后空格原因引起业务异常,所以我们需要去除参数的前后空格! 如果我们手动去除参数前后空格,我们可以这样做 @GetMapping(value ...

  10. 如何实现 Java SpringBoot 自动验证入参数据的有效性

    Java SpringBoot 通过javax.validation.constraints下的注解,实现入参数据自动验证 如果碰到 @NotEmpty 否则不生效,注意看下 @RequestBody ...

随机推荐

  1. 面试题一《swift和oc的区别》

    一.来源 这道题来自网上一篇文章<100家公司iOS面试题管理>,这份题目虽然题目质量不高,但是覆盖面比较全,有学习的价值 二.解析 1.swift 比 OC更年轻,这意味着 swift ...

  2. flutter 打包web应用指定上下文

    使用flutter build web命令打包的应用不包含上下文,只能部署在根目录.如何指定上下文,部署在子目录下呢? 有两种办法: 1.修改web/index.html文件 修改 <base ...

  3. 一个或多个C文件编译KO

    参考文档:.c文件如何编译为ko的MAKEFILE文件编写 - young525 - 博客园 (cnblogs.com) 文档组织结构 header目录:存放头文件 source目录:存放源文件 单个 ...

  4. pandas基础--汇总和计算描述统计

    pandas含有是数据分析工作变得更快更简单的高级数据结构和操作工具,是基于numpy构建的. 本章节的代码引入pandas约定为:import pandas as pd,另外import numpy ...

  5. 大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异

    最近有客户在使用 Elasticsearch 搜索服务时发现集群有掉节点,并且有 master 收集节点信息超时的日志,节点的负载也很高,不只是 data 节点,master 和协调节点的 cpu 使 ...

  6. Console LDAP 配置解密

    之前通过短视频向大家介绍了 Console 如何集成 LDAP,但很多小伙伴反映按照视频里的配置后不成功.今天就结合小伙伴们反映的问题来跟大家详细介绍一下. Console LDAP 完整的配置参数如 ...

  7. go.mod file not found in current directory or any parent directory; see 'go help modules' (exit status 1)

    go.mod file not found in current directory or any parent directory; see 'go help modules' (exit stat ...

  8. nginx rewrite实践

    nginx rewrite跳转(高级) 官网 https://nginx.org/en/docs/http/ngx_http_rewrite_module.html 该ngx_http_rewrite ...

  9. 实战分析Java的异步编程,并通过CompletableFuture进行高效调优

    一.写在开头 在我们一开始讲多线程的时候,提到过异步与同步的概念,这里面我们再回顾一下: 同步:调用方在调用某个方法后,等待被调用方返回结果:调用方在取得被调用方的返回值后,再继续运行.调用方顺序执行 ...

  10. python生成随机四位数和AttributeError: module 'random' has no attribute 'sample'

    python生成随机四位数和AttributeError: module 'random' has no attribute 'sample' ## AttributeError: module 'r ...