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'仅控制响应内容的解析规则,而错误发生在请求发送前的阶段,和响应处理逻辑完全无关,自然不生效。
- 设置
常见触发场景有三类:
- 追加到FormData的字段中存在未做类型转换的纯对象值:FormData的
append方法仅接受Blob/File、字符串、数字类型的值,如果你直接传入一个JS对象,该值会被自动转成[object Object]字符串,部分Angular版本在处理FormData字段时会误将这类字符串做JSON解析,直接抛出错误。 - 全局HTTP拦截器逻辑冲突:如果项目里自定义了HttpInterceptor,对所有请求的body统一做了JSON序列化/反序列化处理,且没有对FormData类型的body做跳过判断,会在拦截器层尝试把FormData对象转成字符串后解析,触发错误。
- Capacitor原生HTTP插件拦截:部分旧版本的Capacitor社区HTTP插件会自动拦截WebView发起的HTTP请求,在原生层错误地将FormData类型的请求体转成JSON处理,触发解析错误。
修复步骤
按顺序排查处理即可:
- 校验所有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)); - 修正请求配置
不要手动给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); - 排查全局拦截器
检查项目中所有HttpInterceptor的实现,如果存在对请求体做统一JSON转换的逻辑,增加FormData类型判断,直接跳过处理:intercept(req: HttpRequest<any>, next: HttpHandler) { // 新增判断:FormData类型请求直接跳过JSON序列化 if (req.body instanceof FormData) { return next.handle(req); } // 其余原有JSON处理逻辑... } - 排查Capacitor HTTP插件配置
如果项目集成了@capacitor-community/http这类原生HTTP插件,先升级到最新稳定版;如果仍有问题,在插件配置中将上传接口的域名加入绕过列表,让请求走WebView原生XHR通道发送即可。
快速验证技巧:如果逐字段校验没有发现对象值,可以临时把所有拦截器、Capacitor原生HTTP插件都关掉,发起一次请求,如果能正常发出,再逐个开启定位冲突点。
内容的提问来源于stack exchange,提问作者Alex Druzenko
相关产品推荐
相关产品推荐

