前端FormData上传文件触发后端body-parser JSON解析报错的问题求解
错误根因定位
- 报错本质是后端全局挂载的
body-parserJSON解析中间件,无差别拦截了multipart/form-data格式的文件上传请求。 - 前端通过
FormData发起POST请求时,请求体开头是浏览器自动生成的multipart边界标识,格式为类似------WebKitFormBoundary7MA4YWxkTrZu0gW的字符串,第一个非空字符就是-。 - 由于后端没有对不同Content-Type的请求做分流,所有进入路由的请求都被JSON解析中间件尝试执行
JSON.parse(),碰到开头的-直接抛出语法错误,完全匹配提供的错误栈触发路径。
解决方案
调整后端中间件分流规则
JSON解析错误的核心诱因是中间件无差别拦截所有请求,需要做两项调整:
- 修改全局JSON解析中间件的匹配规则,仅拦截Content-Type为
application/json的普通接口请求,不对multipart请求做解析 - 为媒体上传接口单独挂载multipart文件解析中间件,将其放在对应路由的处理链路最前面,确保multipart格式的请求不会流入JSON解析逻辑
参考正确的中间件挂载示例(匹配代码里通过req.files取文件的逻辑,对应express-fileupload组件):
// 错误的全局拦截写法(当前问题的来源) // app.use(express.json()); // 正确配置 // 1. JSON解析仅匹配JSON类型请求 app.use(express.json({ type: 'application/json' })) // 2. 上传路由单独挂载multipart解析组件 const fileUpload = require('express-fileupload'); app.use('/api/media', fileUpload(), mediaRouter);
修正前端服务配置
当前前端服务代码中手动设置了空的请求头对象,需要调整:
- 上传FormData时禁止手动设置
Content-Type: multipart/form-data,否则浏览器不会自动填充请求所需的boundary参数,会引发新的解析错误 - 直接移除手动设置的空
HttpHeaders实例,让浏览器自动为FormData请求配置正确的请求头:
public saveAWS(data: FormData): Observable<any> { return this.http.post('http://localhost:5007/api/media', data); }
修复后端业务逻辑的隐藏Bug
解决JSON解析报错后,以下代码问题会继续导致上传流程异常:
- 路由定义笔误:后端路由中
router.route('http://localhost:5007/api/media')的写法不符合Express规范,路由仅支持相对路径定义,正确写法为router.route('/media'),由上层应用挂载时统一配置全局路径前缀(如app.use('/api', mediaRouter))。 - 字段校验拼写错误:校验
path字段时的错误提示误写为"El campo patch esta vacio",需修正为对应path字段的提示。 - 错误的文件读取逻辑:Node后端环境不存在前端式的
FileReaderAPI,代码中通过new FileReader()读取文件的写法无法正常执行。express-fileupload组件拿到的文件对象本身就携带文件buffer,可直接作为S3上传的入参Body,无需额外读取:const fileName = moment().unix().toString() + '_' + file.name; const params = { Bucket: config.s3.bucket, Body: file.data, // 直接使用文件buffer替代FileReader读取的结果 Key: `${path}/${fileName}`, ContentType: file.mimetype, ACL: 'public-read' } - 无意义的异步操作:代码中
data["url"] = await url的写法冗余,url是手动拼接的静态字符串,不需要异步等待。
内容的提问来源于stack exchange,提问作者sagar
相关产品推荐
相关产品推荐

