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

Web-图片上传出现的错误

前后端数据格式的交互方式不匹配


​问题根源​

  1. ​后端期望的格式​​(LostItemController.java):

    • 使用 @RequestPart LostItemRequestDTO request 接收 ​​JSON 对象​​(自动反序列化)
    • 使用 @RequestPart MultipartFile image 接收 ​​文件​
    • 要求 Content-Type: multipart/form-data
  2. ​前端实际发送的格式​​:

    • 将 JSON 数据以字符串形式放在 request 字段(formData.append('request', JSON.stringify(requestData))
    • 后端无法自动反序列化 request 字段中的 JSON 字符串,导致 ​​415 错误​

解决方案​

​方案1:修改前端 - 直接发送对象而非 JSON 字符串​

前端不需要手动 JSON.stringify,直接让 FormData 按字段拆分

async submitForm() {const formData = new FormData();// 直接添加字段(不要包裹成 JSON 字符串)formData.append('category', this.formData.category);formData.append('description', this.formData.description);formData.append('lostLocation', this.formData.lostLocation);formData.append('lostTime', new Date(this.formData.lostTime).toISOString());// 添加图片if (this.formData.image) {formData.append('image', this.formData.image);}try {const response = await fetch('/api/lost', {method: 'POST',body: formData, // 不要手动设置 Content-Type!});// 处理响应...} catch (error) {alert('提交失败: ' + error.message);}
}

方案2:修改后端 - 手动解析 JSON 字符串​

如果必须保持前端发送 request 字段,后端需调整:

@PostMapping(value = "/lost", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result add(@RequestPart String request,  // 改为接收字符串@RequestPart(required = false) MultipartFile image
) {// 手动解析 JSONLostItemRequestDTO requestData = new ObjectMapper().readValue(request, LostItemRequestDTO.class);// 后续逻辑...
}
 

后端无法反序列化前端发送的 LostItemRequestDTO 对象​​,具体错误为:

Cannot construct instance of `com.text.pojo.LostItemRequestDTO` 
(no Creators, like default constructor, exist)

确保前后端字段名严格一致(尤其是 image

问题根源​

  1. ​后端问题​​:

    • LostItemRequestDTO 类缺少 ​​默认构造函数​​ 或 ​​Jackson 反序列化所需的注解​​。
    • Spring 无法将前端传来的 JSON 数据自动转换为 LostItemRequestDTO 对象。
  2. ​前端问题​​:

    • 当前前端发送的是 ​FormData​,但后端期望的是 ​multipart/form-data 中的 JSON 对象​​(@RequestPart LostItemRequestDTO request

解决办法:

修复后端 DTO 类(推荐)​

在 LostItemRequestDTO 中添加 ​​无参构造函数​​ 和 ​​Setter 方法​

package com.text.pojo;public class LostItemRequestDTO {private String category;private String description;private String lostLocation;private String lostTime;// 1. 必须添加无参构造函数public LostItemRequestDTO() {}// 2. 必须提供所有字段的 getter/setterpublic String getCategory() { return category; }public void setCategory(String category) { this.category = category; }// 其他字段的 getter/setter...
}

方案2:修改后端控制器(手动解析 JSON)​

如果无法修改 DTO,可以手动解析 JSON:

@PostMapping(value = "/lost", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result add(@RequestPart String request,  // 改为接收字符串@RequestPart(required = false) MultipartFile image
) {// 手动解析 JSONObjectMapper objectMapper = new ObjectMapper();LostItemRequestDTO requestData = objectMapper.readValue(request, LostItemRequestDTO.class);// 后续逻辑...
}

方案3:调整前端请求格式​

如果后端坚持用 @RequestPart LostItemRequestDTO request,前端需要 ​​按字段拆分 FormData​​(不推荐,但可行):

const formData = new FormData();
formData.append('category', this.formData.category);
formData.append('description', this.formData.description);
formData.append('lostLocation', this.formData.lostLocation);
formData.append('lostTime', this.formData.lostTime);
formData.append('image', this.formData.image);

问题根源​

  1. LocalDateTime 反序列化失败​​:

    • 前端发送的 lostTime 是字符串(如 "2025-06-05T20:06:13"),但后端无法自动将其转换为 LocalDateTime
    • 需要为 LocalDateTime 配置自定义反序列化器。
  2. ​DTO 构造函数冲突​​:

    • 虽然提供了无参构造函数,但还存在全参构造函数,可能导致 Jackson 混淆。

​解决方案​

​1. 修复 DTO 类​

package com.text.pojo;import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import java.time.LocalDateTime;public class LostItemRequestDTO {private String category;private String description;private String lostLocation;@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") // 指定日期格式@JsonDeserialize(using = LocalDateTimeDeserializer.class) // 使用反序列化器private LocalDateTime lostTime;// 只保留无参构造函数public LostItemRequestDTO() {}// 移除全参构造函数(避免干扰 Jackson)// getters/setters...
}
2. 修改前端时间格式​

确保前端发送的时间字符串格式与 @JsonFormat 一致:

// 前端代码(格式化时间)
const requestData = {category: this.formData.category,description: this.formData.description,lostLocation: this.formData.lostLocation,lostTime: new Date(this.formData.lostTime).toISOString().slice(0, 19) // 格式:YYYY-MM-DDTHH:mm:ss
};formData.append('request', JSON.stringify(requestData));
  1. jackson 的默认行为​​:

    • 优先尝试用无参构造函数 + setter(成功)
    • ​但如果类中只有全参构造函数​​(没有无参构造),Jackson 会尝试用它,此时必须满足:
      • 参数名称 ​​严格匹配​​ JSON 字段名
      • 或使用 @JsonProperty 标注参数
  2. ​您的实际错误​​:

    • 虽然提供了无参构造函数,但全参构造函数的存在 ​​干扰了 Jackson 的决策​​(尤其在高版本 Jackson 中)
    • 更关键的是:LocalDateTime 字段没有配置反序列化规则(主因)
http://www.lqws.cn/news/155557.html

相关文章:

  • 通过Chain Prompts方式将LLM的能力引入测试平台:正交实验测试用例生成
  • 国芯思辰|SCS5501/5502芯片组打破技术壁垒,重构车载视频传输链路,兼容MAX9295A/MAX96717
  • ServBay 1.13.0 更新,新增第三方反向代理/内网穿透
  • 【Android基础回顾】一:Binder机制是什么?有什么用?
  • Kaggle-Predicting Optimal Fertilizers-(多分类+xgboost)
  • npm install 相关命令
  • 第46节:多模态分类(图像+文本)
  • 【高等数学】傅里叶级数逼近例子
  • 阿里云 Linux 搭建邮件系统全流程及常见问题解决
  • STM32中自动生成Flash地址的方法
  • 肿瘤相关巨噬细胞(TAM)
  • DeepSeek 赋能智能养老:情感陪伴机器人的温暖革新
  • Vue 中组件命名与引用
  • NoSQL 之 Redis 配置与优化
  • C++ 重载和模板
  • 美化显示LLDB调试的数据结构
  • 数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
  • 【达梦数据库】OOM问题排查思路
  • 03 Deep learning神经网络的编程基础 代价函数(Cost function)--吴恩达
  • 机器学习——什么时候使用决策树
  • Django之表格上传
  • JUnit
  • 实现单例模式的常见方式
  • 基于Java(SpringBoot、Mybatis、SpringMvc)+MySQL实现(Web)小二结账系统
  • 一、ES6-let声明变量【解刨分析最详细】
  • 华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
  • 快速用 uv 模拟发布一个 Python 依赖包到 TestPyPI 上,以及常用命令
  • 机器学习实验八--基于pca的人脸识别
  • 游戏开发中的CI/CD优化案例:知名游戏公司Gearbox使用TeamCity简化CI/CD流程
  • 深入解析CI/CD开发流程