You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何设置MultipartFile请求参数为非必填

问题背景
  • 基于Java Spring Boot开发Portfolio实体编辑接口,接口同时接收实体属性与图片文件,设计逻辑为:参数为空时保留实体原有值,仅更新携带有效值的属性。
  • 接口在Postman中测试运行正常,但从Angular表单提交undefined/null值的图片属性时,后端抛出如下错误:
Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]
  • 目标:实现MultipartFile类型文件参数支持空值,提交空值时接口不报错。

原控制器代码如下:

@PutMapping("/portfolio/edit-data")
public Portfolio editPortfolio (@RequestParam("image")MultipartFile image,
                                  @ModelAttribute("port") Portfolio port,
                                  BindingResult result){
    
    Portfolio portOriginal = portServ.buscarPortfolio(Long.valueOf(1));
    
    if(!image.isEmpty()){
        String rutaAbsoluta = "C:\\Users\\Paul";
        try{
            byte[] bytesImg = image.getBytes();
            Path fullPath = Paths.get(absolutePath + "//" + image.getOriginalFilename());
            Files.write(fullPath, bytesImg);
            port.setImage(image.getOriginalFilename());
        }catch (IOException e){
        }
    }else{
        port.setImage(portOriginal.getImagen());
    }
    
    if("".equals(port.getName())){
        port.setName(portOriginal.getName());
    }
    if("".equals(port.getTitle())){
        port.setTitle(portOriginal.getTitle());
    }
    if("".equals(port.getIntroduction())){
        port.setIntroduction(portOriginal.getIntroduction());
    }
    if("".equals(port.getFooter())){
        port.setFooter(portOriginal.getFooter());
    }
 
    return portServ.editarPortfolio(port, Long.valueOf(1));
}
故障原因
  1. @RequestParam注解默认配置为required = true,强制要求请求中必须携带对应参数/part。Angular提交时如果图片字段为undefined/null,构造FormData时会直接省略该part,后端接收不到对应part就会抛出MissingServletRequestPartException。Postman测试正常是因为测试空场景时通常会保留文件字段、仅上传空内容,和Angular省略字段的提交行为不一致。
  2. 原代码存在两处逻辑缺陷:
    • 定义了路径变量rutaAbsoluta,写文件时误用了未定义的absolutePath变量,会触发运行错误
    • 字符串属性仅判断了空字符串场景,未处理null值,Angular提交undefined/null时后端接收到null,原有空判断会失效,无法正确保留原值
修复方案

后端代码调整

给文件参数的@RequestParam注解添加required = false声明非必填,同时修复原有代码缺陷:

@PutMapping("/portfolio/edit-data")
public Portfolio editPortfolio (@RequestParam(value = "image", required = false) MultipartFile image,
                                  @ModelAttribute("port") Portfolio port,
                                  BindingResult result){
    
    Portfolio portOriginal = portServ.buscarPortfolio(Long.valueOf(1));
    String rutaAbsoluta = "C:\\Users\\Paul";
    
    // 同时判断image不为null、内容不为空
    if(image != null && !image.isEmpty()){
        try{
            byte[] bytesImg = image.getBytes();
            Path fullPath = Paths.get(rutaAbsoluta + "//" + image.getOriginalFilename());
            Files.write(fullPath, bytesImg);
            port.setImage(image.getOriginalFilename());
        }catch (IOException e){
            // 不要空吞异常,建议添加日志打印
            e.printStackTrace();
        }
    }else{
        port.setImage(portOriginal.getImagen());
    }
    
    // 补充null值判断
    if(port.getName() == null || "".equals(port.getName())){
        port.setName(portOriginal.getName());
    }
    if(port.getTitle() == null || "".equals(port.getTitle())){
        port.setTitle(portOriginal.getTitle());
    }
    if(port.getIntroduction() == null || "".equals(port.getIntroduction())){
        port.setIntroduction(portOriginal.getIntroduction());
    }
    if(port.getFooter() == null || "".equals(port.getFooter())){
        port.setFooter(portOriginal.getFooter());
    }
 
    return portServ.editarPortfolio(port, Long.valueOf(1));
}

前端Angular适配(可选,建议同步配置)

构造FormData时即使文件为空也不要省略image字段,空值时传空字符串即可,保证前后端提交行为和Postman测试一致:

const formData = new FormData();
// 普通字段空值时传空字符串,避免后端接收到null
formData.append('name', this.form.get('name')?.value || '');
formData.append('title', this.form.get('title')?.value || '');
formData.append('introduction', this.form.get('introduction')?.value || '');
formData.append('footer', this.form.get('footer')?.value || '');
// 文件字段存在则传文件,不存在则传空字符串,不要跳过append
const imageFile = this.form.get('image')?.value;
if (imageFile) {
  formData.append('image', imageFile, imageFile.name);
} else {
  formData.append('image', '');
}
// 发起PUT请求提交formData即可

内容的提问来源于stack exchange,提问作者Charly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:06:25