PAYATHON 2026

Blazor 上传文件时为何收到 405 MethodNotAllowed?

数据小许

结论

HTTP 405 表示请求到达的地址不接受当前 HTTP 方法。现有信息还无法确定是哪一层返回了 405。上传方法的断点未命中,说明请求没有执行到该方法,但不能据此判断文件流或文件大小有问题。先确认客户端实际请求的完整 URL,以及服务端匹配到的路由和响应来源。

原控制器上的 [Route("api/[controller]")] 与 [HttpPost("restore")] 组合后,POST 路由应为 api/Utility/restore。客户端的 route 是相对地址,最终 URL 还取决于 _apiHttpClient.BaseAddress。可以检查响应对应的请求地址:

var response = await _apiHttpClient.PostAsync(route, content);

Console.WriteLine(response.RequestMessage?.RequestUri);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Headers.Allow);

如果响应中包含 Allow 头,它可能列出该地址允许使用的方法。也可以查看 API 服务端日志,确认请求是否到达预期应用,以及匹配到了哪个端点。

逐项排查

  1. 核对实际 URL 和请求方法。 确认 RequestUri 指向 API 的主机和预期路径,而不是 Blazor 应用地址、错误的代理路径或另一项服务。对同一 URL 直接发送 POST,并与 GET 下载地址对照。

  2. 核对端点路由。 原控制器的路由属性对应 api/Utility/restore。如果部署时经过反向代理或网关,也要确认它没有改写路径或限制 POST。

  3. 查看 405 的响应来源。 检查响应头、响应体和服务端日志。如果 API 日志里没有这条请求,405 可能由代理、Web 服务器或其他服务返回;如果请求已到达 API,就检查该路径上实际注册的端点和允许的方法。

  4. 再检查 multipart 字段绑定。 客户端发送的字段名是 file:

    content.Add(streamContent, "file", browserFile.Name);

    控制器参数名则是 theFile。两边应使用相同名称,例如把客户端字段名改为 theFile:

    content.Add(streamContent, "theFile", browserFile.Name);

    也可以在服务端显式指定名称:

    public async Task<IActionResult> UploadFile([FromForm(Name = "file")] IFormFile theFile)

    字段名不匹配会影响表单文件绑定,通常不会直接导致 405。修正路由后,如果绑定仍然失败,再检查这一项。

关于 CORS 和后续代码

AllowAnyMethod() 配置的是 CORS 策略允许的方法,不会让不存在或不接受 POST 的路由自动接受 POST。浏览器发起跨域请求时,可能先发送 OPTIONS 预检请求。可以在浏览器网络面板查看失败请求的方法和响应。如果失败的是预检请求,就检查 CORS 中间件是否应用于该请求,以及实际请求是否进入了正确的 API。

后续代码在控制器上保留了 [Route("api/[controller]")],又在操作方法上写了 [Route("api/utility/restore")]。ASP.NET Core 通常会组合控制器和操作方法的路由模板,因此最终路径可能多出一段。由控制器路由提供前缀时,操作方法只需声明 [HttpPost("restore")];如果要指定完整路由,可以使用 [HttpPost("~/api/utility/restore")],这样就不会与控制器路由组合。请根据应用实际注册的路由确认最终地址。

修正路由和字段名后,再确认请求是否确实以 POST 到达该端点。现有信息不足以确定 405 的唯一来源,不能只凭 CORS 配置或流长度推断故障点。

备注:内容仅供参考。