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

Angular 13向Java后端提交FormData请求报400/415错误

Angular 13 发送FormData到Java后端请求异常解决方案

问题复现代码

前端 Service 代码(applicationservice.ts)

aggiungiApplicazione(appForm: FormData): Observable<Applicazione> {
  return this.http.post<Applicazione>(`http://localhost:8080/Gestionale/api/applicazione/aggiunta`, appForm, {headers: { "Content-Type": "application/json" }});
}

前端组件代码(component.ts)

const appFormData = new FormData();

Object.keys(this.appForm).map((key) => {
  appFormData.append(key, this.appForm[key].value);
})


_aggiungiApplicazione(appData: FormData) {
this.applicazioneService.aggiungiApplicazione(appData).subscribe((app: Applicazione) => {
  console.log(app);
  timer(2000).toPromise().then(() => {
    this.display = false;
    this._getApplicazioni();
  })
});
}

后端接口代码

@POST
@Path("aggiunta")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Applicazione add(Applicazione a) {
    JpaDaoFactory.getDaoFactory().save(a);
    return a;
}

报错表现

  • 手动指定Content-Type: application/json请求头时,返回400 Bad Request:

ERROR
Type Status Report
Message Bad Request
Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

  • 移除手动配置的Content-Type请求头后,返回415 Unsupported Media Type错误。

故障原因

前后端请求数据格式配置完全不匹配:

  1. 手动给FormData请求设置application/json头时,请求体实际是多段分隔的二进制FormData格式,后端按JSON规则解析必然失败,触发400错误。
  2. 删掉手动设置的请求头后,浏览器会自动给FormData请求加上multipart/form-data头(附带自动生成的boundary分隔符,这个参数不能手动设置),但后端接口通过@Consumes(MediaType.APPLICATION_JSON)配置了只接收JSON格式请求,识别不了form-data类型,直接返回415错误。

修复方案

根据业务是否有文件上传需求二选一:

方案1:无文件上传场景(改动最小)

不需要构造FormData,直接发送JSON格式数据,后端代码完全不用改:

  1. 修改组件逻辑,删掉FormData构造代码,直接传表单值:
_aggiungiApplicazione() {
  const appData = this.appForm.value;
  this.applicazioneService.aggiungiApplicazione(appData).subscribe((app: Applicazione) => {
    console.log(app);
    timer(2000).toPromise().then(() => {
      this.display = false;
      this._getApplicazioni();
    })
  });
}
  1. 修改Service层代码,删掉手动设置的Content-Type头,Angular会自动给JSON请求配置正确的请求头:
aggiungiApplicazione(appForm: Partial<Applicazione>): Observable<Applicazione> {
  return this.http.post<Applicazione>(`http://localhost:8080/Gestionale/api/applicazione/aggiunta`, appForm);
}

方案2:包含文件上传、必须用FormData的场景

需要同时修改前后端配置,匹配multipart/form-data格式:

  1. 前端Service层删掉手动设置的Content-Type头,绝对不能手动设置这个头,否则会丢失浏览器自动生成的boundary参数,直接导致后端解析失败:
aggiungiApplicazione(appForm: FormData): Observable<Applicazione> {
  return this.http.post<Applicazione>(`http://localhost:8080/Gestionale/api/applicazione/aggiunta`, appForm);
}
  1. 修改后端接口配置,将@Consumes的值改为MediaType.MULTIPART_FORM_DATA,同时调整参数接收方式。如果是Jersey框架,需要先引入multipart解析依赖,再通过@FormParam接收普通字段、@FormDataParam接收文件字段;如果是Spring Boot框架,直接用@RequestPart或@ModelAttribute注解绑定参数到实体类即可。
    示例(Jersey框架):
@POST
@Path("aggiunta")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Applicazione add(
  @FormParam("nome") String nome,
  @FormParam("descrizione") String descrizione
) {
    Applicazione a = new Applicazione();
    a.setNome(nome);
    a.setDescrizione(descrizione);
    JpaDaoFactory.getDaoFactory().save(a);
    return a;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 01:27:33