当前位置: 首页 > 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 字段没有配置反序列化规则(主因)

相关文章:

  • Apache Druid 架构深度解析:构建高性能分布式数据存储系统
  • 第十三节:第四部分:集合框架:HashMap、LinkedHashMap、TreeMap
  • 联邦学习架构深度分析:支持多家医院协作训练AI模型方案分析
  • vue3 eslint ts 关闭多单词命名检查
  • kafka部署
  • 2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
  • 【Linux篇】0基础之学习操作系统进程
  • SpringCloud——Nacos
  • 免费工具-微软Bing Video Creator
  • 【十年技术演进深度解构:车载充电机(OBC)将成为新能源汽车的“能源大脑”】
  • 软件工程:如何做好软件产品
  • 高效集成AI能力:使用开放API打造问答系统,不用训练模型,也能做出懂知识的AI
  • 倍福 PLC程序解读
  • Linux服务器如何安装wps?
  • 可编辑PPT | 基于大数据中台新能源智能汽车应用解决方案汽车大数据分析与应用解决方案
  • 新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
  • 人工智能的社交课:从博弈游戏到健康关怀
  • elasticsearch-8.17.4
  • Windows 10 IoT 系统深度定制指南:从环境搭建到工业部署
  • 【物联网-S7Comm协议】
  • 生态农业网站模板/百度公司全称
  • 国外 网站有做验证码吗/微信推广广告在哪里做
  • b2b网站运营/网络营销推广方案3篇
  • 淄博团购网站建设/百度地图轨迹导航
  • 模板网站有什么不好/it培训机构排名及学费
  • 太原有哪些做网站的公司/免费seo优化工具