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

Angular使用FormData发起HTTP POST报Unexpected Token错误

问题根因

这个错误发生在Angular HttpClient请求发起前的内部处理阶段,请求根本没有发送到网络层,和后端服务无关,对应错误Unexpected token o in JSON at position 1的触发逻辑非常明确:

  • 该错误是执行JSON.parse()解析值为[object Xxx]格式的字符串时抛出的典型错误:字符串首字符[符合JSON数组的起始标记,但位置1的字符o完全不符合JSON语法,直接触发解析失败。
  • 你之前尝试的两种修复方案无效的原因:
    • 设置Content-Type: application/x-www-form-urlencoded仅支持普通键值对表单提交,完全不兼容带Blob/File的文件上传场景,也没有解决触发JSON解析错误的核心问题
    • 配置responseType: 'text'仅控制响应内容的解析规则,而错误发生在请求发送前的阶段,和响应处理逻辑完全无关,自然不生效。

常见触发场景有三类:

  1. 追加到FormData的字段中存在未做类型转换的纯对象值:FormData的append方法仅接受Blob/File、字符串、数字类型的值,如果你直接传入一个JS对象,该值会被自动转成[object Object]字符串,部分Angular版本在处理FormData字段时会误将这类字符串做JSON解析,直接抛出错误。
  2. 全局HTTP拦截器逻辑冲突:如果项目里自定义了HttpInterceptor,对所有请求的body统一做了JSON序列化/反序列化处理,且没有对FormData类型的body做跳过判断,会在拦截器层尝试把FormData对象转成字符串后解析,触发错误。
  3. Capacitor原生HTTP插件拦截:部分旧版本的Capacitor社区HTTP插件会自动拦截WebView发起的HTTP请求,在原生层错误地将FormData类型的请求体转成JSON处理,触发解析错误。
修复步骤

按顺序排查处理即可:

  1. 校验所有FormData字段值
    在发起请求前逐字段打印追加到FormData的值,确认没有直接传入纯对象:
    // 排查时临时加的校验代码
    console.log(data.get('fileId'), typeof params.fileId)
    console.log(data.get('pagenumber'), typeof params.pageNum)
    console.log(data.get('appid'), typeof this.appMod.appId)
    console.log(data.get('sessionid'), typeof this.appMod.sessionId)
    // 其余省略的字段同理校验
    
    如果打印值为[object Object],说明该字段传值错误,提前转成后端需要的基础类型(字符串/数字)再追加,兜底可以统一用String()转义:
    data.append('fileId', String(params.fileId));
    data.append('pagenumber', String(params.pageNum));
    data.append('appid', String(this.appMod.appId));
    data.append('sessionid', String(this.appMod.sessionId));
    
  2. 修正请求配置
    不要手动给FormData请求设置Content-Type头,让浏览器自动生成带boundary分隔标记的multipart/form-data头,同时明确配置项的TS类型避免推导异常:
    const reqOptions = {
      headers: new HttpHeaders(), // 不要设置Content-Type
      responseType: 'json' as const
    };
    
    const data = new FormData();
    data.append(name, blobFile, "TestName");
    // 追加其余基础类型字段...
    
    return this.http.post(webServiceUrl, data, reqOptions);
    
  3. 排查全局拦截器
    检查项目中所有HttpInterceptor的实现,如果存在对请求体做统一JSON转换的逻辑,增加FormData类型判断,直接跳过处理:
    intercept(req: HttpRequest<any>, next: HttpHandler) {
      // 新增判断:FormData类型请求直接跳过JSON序列化
      if (req.body instanceof FormData) {
        return next.handle(req);
      }
      // 其余原有JSON处理逻辑...
    }
    
  4. 排查Capacitor HTTP插件配置
    如果项目集成了@capacitor-community/http这类原生HTTP插件,先升级到最新稳定版;如果仍有问题,在插件配置中将上传接口的域名加入绕过列表,让请求走WebView原生XHR通道发送即可。

快速验证技巧:如果逐字段校验没有发现对象值,可以临时把所有拦截器、Capacitor原生HTTP插件都关掉,发起一次请求,如果能正常发出,再逐个开启定位冲突点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:39:22