Express服务无法接收带config的Axios POST请求解决方案
问题根因
报错核心原因是后端没有处理浏览器自动发起的OPTIONS预检请求,和Axios传不传config参数没有直接关系:
- 不传
onUploadProgress配置时,Axios发出的是符合规范的简单跨域请求,浏览器不会提前发校验请求,直接把POST请求发到后端,你写在POST路由里的Access-Control-Allow-Origin: *头能正常生效,所以请求能跑通。 - 一旦传入
onUploadProgress配置,Axios会基于XHR的进度事件实现上传进度监听,此时请求会被浏览器判定为非简单跨域请求:正式发POST请求前,浏览器会先发一个OPTIONS方法的预检请求,检查后端是否允许当前跨域调用、是否支持对应的请求方法和请求头。你现在的代码只在POST路由里写了CORS相关响应头,既没有匹配OPTIONS方法的路由,也没有返回预检要求的完整CORS头,预检直接失败,浏览器就会拦截后续的正式POST请求,抛出CORS错误。
你测试公共接口正常,是因为公共接口服务端默认配置了完整的CORS规则,自动处理了OPTIONS预检,和你的前端代码没有关系。
解决方案
两种实现方式,优先选第一种,配置简单不容易漏规则。
方案1:使用官方cors中间件(推荐)
先安装依赖:
npm install cors
在所有路由加载之前全局注册中间件即可,中间件会自动处理OPTIONS预检、返回所有要求的CORS响应头,不用在单个路由里重复写头信息:
const express = require('express'); const cors = require('cors'); const app = express(); // 全局开启CORS支持 app.use(cors()); // 注册你的上传路由 const uploadRouter = require('./routes/upload'); app.use('/upload', uploadRouter);
如果要做更细的权限控制,可以传入自定义配置:
app.use(cors({ origin: '*', // 生产环境替换为前端实际部署域名,不要长期用通配符 methods: ['GET', 'POST', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'Content-Length'] }));
方案2:手动实现CORS中间件(无第三方依赖)
不想额外装包的话,可以自己写一个全局中间件统一处理CORS逻辑,注意必须把这个中间件放在所有业务路由之前注册:
// CORS统一处理中间件 app.use((req, res, next) => { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization'); // 直接响应OPTIONS预检请求,不需要进入后续业务逻辑 if (req.method === 'OPTIONS') { return res.sendStatus(200); } next(); }); // 你的上传路由 router.post('/', (request, response) => { console.log(request); // 记得给请求返回响应,否则前端会一直处于等待状态 response.json({ code: 200, msg: '上传接口连通' }); });
后续注意事项
- 现在的POST路由没有返回任何响应,就算CORS配置正常,前端请求也会超时,处理完逻辑一定要返回响应结果。
- 后续解析FormData上传的文件时,不要用Express内置的
express.json()、express.urlencoded()中间件,这两个中间件无法解析multipart/form-data格式的请求体,需要用multer这类专门处理文件上传的中间件。 - 生产环境不要长期使用
*作为允许的源,替换为前端实际的访问域名,降低跨域安全风险。
内容的提问来源于stack exchange,提问作者Mihkel Pajunen
相关产品推荐
相关产品推荐

