为何React发送FormData POST请求时不跟随Flask 307重定向?
核心问题定位
fetch配置存在无效字段:fetch的参数对象根本不识别config属性,你写的headers配置完全没有生效。更关键的是,手动强制设置Content-Type: multipart/form-data会覆盖浏览器为FormData请求自动生成的、带随机boundary分隔符的请求头,直接导致服务端无法解析请求体,触发连接重置。- 跨域重定向的浏览器限制:跨域场景下浏览器拿到307响应后,会先校验初始响应的CORS权限,再把原始POST请求(带文件的FormData体)透传到重定向地址。如果初始307响应没有带正确的CORS头、或者请求地址本身存在域不匹配,浏览器会直接中断请求,不会发起到目标端点的第二次请求。
- 本地开发的地址错配:前端从
localhost域发起请求时,调用http://0.0.0.0:5001会被浏览器判定为跨域请求,哪怕服务端开了CORS也可能被拦截。
对应修复步骤
1. 修正客户端fetch配置
删除所有无效的配置项,让浏览器自动处理FormData的请求头,修正后的代码如下:
uploadAPI = async (formData) => { // 将API_SERVER_URL替换为127.0.0.1,不要用0.0.0.0 fetch(`${API_SERVER_URL}${this.state.destpath}`, { method: "POST", redirect: 'follow', body: formData, mode: 'cors', // 大文件场景关闭keepalive,避免请求体被截断 keepalive: false }).then((res) => { console.log("响应状态", res.status); if (res.ok) { alert("File uploaded successfully."); } }).catch(err => { console.error("请求失败详情", err); }); };
注意:当请求体是FormData实例时,浏览器会自动生成带正确boundary的multipart/form-data请求头,手动设置一定会导致请求解析失败。
2. 全局配置Flask CORS
仅在单个路由上加@cross_origin()无法覆盖307重定向响应的CORS校验,需要全局初始化CORS规则,确保所有响应(包括307状态的重定向响应)都带上合法的跨域头:
from flask_cors import CORS app = Flask(__name__) # 全局配置CORS,允许所有源的FormData请求 CORS(app, resources={r"/*": {"origins": "*", "allow_headers": "*"}}) # 后续路由不需要单独加@cross_origin装饰器 @app.route('/upload/redirect', methods = ['POST', 'GET']) def index(): print("Redirect request received!") return "redirect", 200, {'Content-Type': 'application/json'} @app.route('/upload/shp', methods = ['POST', 'GET']) def file_recv_shp_node(): return redirect(url_for('index'), code=307)
3. 连通性验证
修正后通过浏览器开发者工具的网络面板检查:
- 发往
/upload/shp的初始POST请求返回307时,响应头必须包含Access-Control-Allow-Origin字段 - 浏览器自动跟随跳转发往
/upload/redirect的请求必须携带完整的FormData请求体,最终返回200状态码
方案优化建议
跨域场景下依赖浏览器自动透传带大文件的307重定向请求存在天然限制:浏览器对重定向携带的multipart请求体有大小阈值,超过阈值会直接中断连接。更稳定的实现是将服务端的307重定向改为返回JSON格式的目标上传地址,由前端拿到地址后直接向最终端点发请求,完全绕开重定向环节的跨域限制。
内容的提问来源于stack exchange,提问作者bmalbusca
相关产品推荐
相关产品推荐

