.NET 6 Web API与React文件上传的CORS及代理问题排查
React上传文件到.NET 6 Web API遇CORS/代理问题
问题现象
- Postman调用文件上传接口正常,但Swagger和React调用均失败
- 无文件上传的POST、GET、PUT接口均可正常使用
- React网络面板报错:
Could not proxy request /api/Employee/SaveFile from localhost:3000 to "https://127.0.0.1:7224/" (ECONNREFUSED)
已尝试操作
- 在
package.json配置代理:"proxy": "https://127.0.0.1:7224/" - 修改React启动命令:
"start": "cross-env DANGEROUSLY_DISABLE_HOST_CHECK=true react-scripts start" - React代码尝试过带/不带
headers的写法
代码片段
React上传代码
imageUpload = (e) => { e.preventDefault(); const formData = new FormData(); formData.append("file", e.target.files[0], e.target.files[0].name); fetch('/api/Employee/SaveFile', { method: 'POST', body: formData, headers : { 'Content-Type': 'multipart/form-data', 'Accept': 'application/json, text/plain' } }) .then(res => res.json()) .then(data => { this.setState({ PhotoFileName: data }); }) }
.NET 6 Program.cs CORS配置
//Enable CORS builder.Services.AddCors(options => { options.AddPolicy(name: "orgEmpPolicy", policy => { policy.WithOrigins("http://localhost:3000/", "http://192.168.1.9:3000/", "http://127.0.0.1:3000/") .WithHeaders(HeaderNames.ContentType) .WithMethods("PUT", "DELETE", "GET", "PATCH", "POST"); }); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseRouting(); app.UseCors("orgEmpPolicy");
.NET 6 控制器代码
[HttpPost] [Route("SaveFile")] public JsonResult SaveFile() { try { var httpRequest = Request.Form; var postedFile = httpRequest.Files[0]; string filename = postedFile.FileName; if (string.IsNullOrWhiteSpace(_env.WebRootPath)) { _env.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"); } var uploads = Path.Combine(_env.WebRootPath, "Photos"); var filePath = Path.Combine(uploads, postedFile.FileName); if (!Directory.Exists(uploads)) _ = Directory.CreateDirectory(Path.GetDirectoryName(filePath)); using (var stream = new FileStream(filePath, FileMode.Create)) { stream.CopyTo(stream); } return new JsonResult(filename); } catch (Exception ex) { return new JsonResult(ex.Message); } }
调试环境
Visual Studio 2022调试Web API,VS Code调试React
解决方案
1. 修复React请求的Content-Type问题
使用FormData上传文件时,禁止手动设置Content-Type: multipart/form-data,浏览器会自动生成包含boundary的正确请求头,手动设置会丢失boundary信息,导致后端无法解析表单,同时触发CORS预检失败。
修改后的React代码:
imageUpload = (e) => { e.preventDefault(); const formData = new FormData(); formData.append("file", e.target.files[0], e.target.files[0].name); fetch('/api/Employee/SaveFile', { method: 'POST', body: formData, headers : { 'Accept': 'application/json, text/plain' } }) .then(res => res.json()) .then(data => { this.setState({ PhotoFileName: data }); }) .catch(err => console.error('上传失败:', err)); }
2. 修正CORS配置的Origin后缀
WithOrigins中的地址不能带斜杠,否则Origin匹配失效。修改Program.cs的CORS配置:
policy.WithOrigins("http://localhost:3000", "http://192.168.1.9:3000", "http://127.0.0.1:3000")
开发环境可临时放宽头限制(生产环境需按需配置):
policy.WithOrigins("http://localhost:3000", "http://192.168.1.9:3000", "http://127.0.0.1:3000") .AllowAnyHeader() .AllowAnyMethod();
3. 校验代理与API地址一致性
- 查看Web API项目的
Properties/launchSettings.json,确认applicationUrl是否为https://127.0.0.1:7224,避免端口/协议不匹配导致连接拒绝 - 若API使用HTTP而非HTTPS,代理地址需改为
http://127.0.0.1:xxxx
4. 修复控制器文件流错误
控制器中stream.CopyTo(stream)会导致无限循环,应改为:
postedFile.CopyTo(stream);
5. 让Swagger支持文件上传
在控制器方法上添加特性,让Swagger识别请求类型:
[HttpPost] [Route("SaveFile")] [Consumes("multipart/form-data")] public JsonResult SaveFile()
内容的提问来源于stack exchange,提问作者Adonis Villanueva
相关产品推荐
相关产品推荐

