Spring Boot 文件上传接口 Postman 测试报错“Required request part ‘file‘ is not present”的解决全过程

提示:Spring Boot 文件上传接口 Postman 测试报错“Required request part ‘file’ is not present”的解决全过程


前言

提示:Required request part 'file' is not present

大家好,我是将军。最近在开发一个基于 Spring Boot 的项目时,遇到了一个让我头疼了两天的文件上传问题:使用 Postman 测试文件上传接口时,总是报错 Required request part 'file' is not present。这个错误看似简单,但排查起来却像剥洋葱,一层一层地深入。最终,我通过参考一篇简书文章(Spring Boot 文件上传解析器配置问题)和项目实际调试,找到了根源——Spring Boot 的默认 MultipartResolver 在某些版本下解析 multipart/form-data 请求时不稳定。以下是我从问题复现到彻底解决的全过程记录,希望能帮到遇到同样坑的开发者。


提示:以下是解决全过程

大家好,我是将军。最近在开发一个基于 Spring Boot 的项目时,遇到了一个让我头疼了两天的文件上传问题:使用 Postman 测试文件上传接口时,总是报错 Required request part 'file' is not present。这个错误看似简单,但排查起来却像剥洋葱,一层一层地深入。最终,我通过参考一篇简书文章(Spring Boot 文件上传解析器配置问题)和项目实际调试,找到了根源——Spring Boot 的默认 MultipartResolver 在某些版本下解析 multipart/form-data 请求时不稳定。以下是我从问题复现到彻底解决的全过程记录,希望能帮到遇到同样坑的开发者。

问题背景与复现

项目是一个分期申请管理系统,使用 Spring Boot 2.x(实际版本 1.4.2.RELEASE,稍后会提到版本影响)。接口是 /api/installmentApplication/importMarkProcessed,用于上传 Excel 文件批量处理分期标记。接口定义如下(简化版):

@PostMapping("/importMarkProcessed")
@RequiresRoles({"CUSTOMER_SERVICE", "CUSTOMER_SERVICE_MANAGER"})
public ResponseEntity<String> importMarkProcessed(@RequestParam("file") MultipartFile file) {
    // 处理文件逻辑...
    return ResponseEntity.ok("上传成功");
}

测试流程(Postman):

  • 请求方式:POST
  • URLhttp://localhost:8080/api/installmentApplication/importMarkProcessed
  • Body:form-data
    • Key:file(Type: File)
    • Value:选择本地 .xlsx 文件
  • Headers:自动生成 Content-Type: multipart/form-data; boundary=...(无手动设置)

发送请求后,控制台直接抛出:

Required request part 'file' is not present

这个错误表示服务器端未接收到名为 file 的 multipart 部分。乍一看是客户端问题,但 Postman 配置明明正确啊!

初步排查:排除常见坑

我先从“万金油”解决方案入手,排查了以下几点(这些是网上最常见的建议):

  1. Postman 配置检查

    • Key 名称严格为 file(小写,无空格)。
    • 文件选择有效(非空 .xlsx 文件,大小 < 10MB)。
    • Headers 中移除手动 Content-Type,让 Postman 自动处理。
    • 生成 cURL 命令测试:curl -X POST -F "file=@/path/to/file.xlsx" http://localhost:8080/...,结果相同错误。
  2. 服务器端基本配置

    • application.properties(或 yml)添加:
      spring.servlet.multipart.enabled=true
      spring.servlet.multipart.max-file-size=10MB
      spring.servlet.multipart.max-request-size=10MB
      
    • 重启服务,测试其他文件上传接口(如 /submit),部分正常,但问题接口仍报错。
  3. 权限与拦截器检查

    • 接口有 Shiro @RequiresRoles,确认 Postman 携带有效 token(通过登录接口获取)。
    • 项目有自定义拦截器 MultipartLoggingInterceptor,但仅针对 /submit,不影响当前路径。
    • 启用 DEBUG 日志(logging.level.org.springframework.web=DEBUG),日志显示请求到达控制器,但 file 参数为 null。

排查了两天,这些都没问题。我开始怀疑是 Spring Boot 版本或底层解析器 bug。最终,在一次无意搜索中,找到了那篇简书文章,点亮了新思路:默认的 StandardServletMultipartResolver 在旧版 Spring Boot 中可能无法正确解析 multipart 请求,建议切换到 ***monsMultipartResolver

深入分析:MultipartResolver 的“黑洞”

Spring Boot 的文件上传依赖 MultipartResolver 来解析 multipart/form-data。默认使用 StandardServletMultipartResolver(基于 Servlet 3.0+),但在 Spring Boot 1.x(如 1.4.2)中,它对某些边界情况(如自定义编码或大文件)处理不稳,导致参数“蒸发”。

  • 为什么是这个版本问题?Spring Boot 2.x 优化了默认解析器,但 1.x 需手动配置 ***monsMultipartResolver(基于 Apache ***mons FileUpload),它更鲁棒,支持更多场景。
  • 项目确认:查看 pom.xml,parent 版本确为 1.4.2.RELEASE。这解释了为什么其他接口偶尔正常(简单文件),但复杂路径(如带 Shiro 拦截)失败。

解决方案:一步步配置 ***monsMultipartResolver

基于文章思路,我本地化了配置,分三步实施。整个过程只需修改三个文件,重启即生效。

步骤 1: 添加依赖

pom.xml<dependencies> 中添加 ***mons-fileupload(如果未存在):

<dependency>
    <groupId>***mons-fileupload</groupId>
    <artifactId>***mons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

位置:项目根目录 pom.xml。运行 mvn clean install 更新依赖。

步骤 2: 排除默认自动配置

application.yml(或 application.properties)中禁用默认 MultipartAutoConfiguration,避免冲突:

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration

位置src/main/resources/application.yml(开发环境用 application-dev.yml)。这步关键,确保自定义 Bean 生效。

步骤 3: 注入自定义 MultipartResolver Bean

在 Web 配置类中添加 Bean。项目已有 WebConfig.java,直接扩展:

package ***.hyham.***mon.config.web;

import org.apache.***mons.logging.Log;
import org.apache.***mons.logging.LogFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.***mons.***monsMultipartResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMv***onfigurer;

@Configuration
public class WebConfig implements WebMv***onfigurer {
    private static final Log log = LogFactory.getLog(WebConfig.class);

    // 现有拦截器注入...
    private final MultipartLoggingInterceptor loggingInterceptor;

    public WebConfig(MultipartLoggingInterceptor loggingInterceptor) {
        this.loggingInterceptor = loggingInterceptor;
    }

    @Bean(name = "multipartResolver")
    public MultipartResolver multipartResolver() {
        log.info("Loading the ***monsMultipartResolver");
        ***monsMultipartResolver resolver = new ***monsMultipartResolver();
        resolver.setMaxUploadSize(10485760L); // 10MB
        resolver.setDefaultEncoding("UTF-8"); // 防中文乱码
        return resolver;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 现有拦截器配置...
        registry.addInterceptor(loggingInterceptor).addPathPatterns("/api/installmentApplication/submit");
    }
}

位置src/main/java/***/hyham/***mon/config/web/WebConfig.java。添加后,日志会输出 “Loading the ***monsMultipartResolver”,确认生效。

测试验证与注意事项

配置完成后,重启项目(mvn spring-boot:run),Postman 测试:

  • 上传相同 .xlsx 文件,接口返回 “上传成功”,日志显示 file 参数非 null,大小正确。
  • 额外测试:上传大文件(>5MB)、中文文件名,全正常。

注意事项

  • 版本适用:Spring Boot 1.x 必备,2.x 可选(默认已优化)。
  • 权限检查:确保 Shiro 角色正确,否则请求被拦截。
  • 文件目录:确认 ${file.upload.dir:/uploads} 目录有写权限(chmod 777 /uploads)。
  • Excel 解析:上传文件需含 “案件号” 和 “申请日期” 表头,否则后续 POI 解析报错。
  • 调试技巧:在控制器添加 log.info("File: {}", file.getOriginalFilename());,快速验证。

如果你的项目是 Spring Boot 2.x+,先试默认配置;否则,这个方案 100% 管用。

总结与感悟

这个 bug 让我深刻体会到:文件上传看似简单,实则涉及 Servlet、Spring 底层和客户端工具的完美协作。两天排查让我从 Postman 调到日志分析,再到源码深挖,最终靠一篇“新思路”文章解围。开发路上,多记录、多分享,才能少走弯路。

如果你也遇到类似问题,欢迎评论区交流!项目源码(脱敏版)可私信索要。点赞收藏不迷路,下篇见~

标签:Spring Boot, 文件上传, Postman, MultipartResolver, Java
相关阅读

  • Spring Boot 官方文件上传文档
  • Apache ***mons FileUpload 指南

我是将军,我一直都在!

转载请说明出处内容投诉
CSS教程网 » Spring Boot 文件上传接口 Postman 测试报错“Required request part ‘file‘ is not present”的解决全过程

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买