子域名调用Express文件上传API时出现CORS错误求助
子域名调用Express文件上传API触发CORS错误的解决办法
问题详情
错误提示:
Access to XMLHttpRequest at 'https://api.mysite.com/api/uploadfile' from origin 'https://sub.mysite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- 环境:子域名
https://sub.mysite.com(Angular前端)调用主域名https://api.mysite.com(Express后端)的API - 异常:其他API接口正常,仅文件上传路由返回CORS错误
- 已尝试:查阅相关问题未解决
后端(Express)代码
// 允许所有跨域请求 this.app.use(cors()); // 文件上传路由 var upload = multer({ storage: storage }); this.router.post("/", passport.authenticate('jwt', { session: false }), upload.single('file'), this.fileController.uploadfile);
前端(Angular)代码
uploadFile(formData: any): Observable<any> { // test 1(已注释) // return Axios.post(`${this.apiURL}test`, formData, { // headers: { // 'Authorization': this._authService.accessToken, // 'Content-Type': 'multipart/form-data' // } // }) // .pipe( // tap((response: any) => { // console.log("response:", response) // }) // ); // test 2(当前使用) const httpOptions = { headers: new HttpHeaders({ 'Authorization': this._authService.accessToken, 'Content-Type': 'multipart/form-data' }) }; return this.http.post<any>(`${this.apiURL}test`, formData, httpOptions) .pipe( tap((response: any) => { console.log("response:", response) }), catchError(this.handleError) ); }
解决步骤
1. 移除前端手动设置的Content-Type
上传FormData时,浏览器会自动生成包含boundary的multipart/form-data头,手动设置会丢失boundary,导致后端Multer无法解析请求,进而返回无CORS头的错误响应。
修正后的前端代码:
uploadFile(formData: any): Observable<any> { const httpOptions = { headers: new HttpHeaders({ 'Authorization': this._authService.accessToken // 移除Content-Type设置,由浏览器自动处理 }) }; return this.http.post<any>(`${this.apiURL}test`, formData, httpOptions) .pipe( tap((response: any) => console.log("response:", response)), catchError(this.handleError) ); }
2. 调整后端CORS中间件顺序
确保cors()中间件在所有路由、Passport认证、Multer配置之前加载,否则文件上传路由可能无法触发CORS头的设置:
// 先加载CORS中间件(明确指定允许的源,比允许所有更安全) this.app.use(cors({ origin: 'https://sub.mysite.com', credentials: true // 如果需要携带认证信息或Cookie })); // 再加载Passport、路由等 this.app.use(passport.initialize()); this.app.use("/api/uploadfile", this.router);
3. 添加全局错误处理中间件
如果Multer解析失败(比如FormData中没有file字段),Express默认返回的错误响应不会携带CORS头,需要添加全局错误处理确保所有响应都包含CORS头:
this.app.use((err, req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://sub.mysite.com'); res.status(err.status || 500).json({ message: err.message || '服务器内部错误' }); });
4. 验证FormData格式
确保前端构造的FormData中确实包含名为file的字段,与后端upload.single('file')的参数一致:
// 示例:正确构造FormData const formData = new FormData(); formData.append('file', fileInput.files[0]); // 字段名必须是'file'
内容的提问来源于stack exchange,提问作者wil
相关产品推荐
相关产品推荐

