You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#控制器接收前端文件报错‘The files field is required’的解决方法

文件上传报错"The files field is required"的解决方案

问题背景

我是C#新手,之前只用JS开发。写了一个C#控制器接收前端传的文件,但一直报错The files field is required,无法解决。

控制器代码

public class FileUploadController : ControllerBase
{
    [HttpPost]
    [Route("fileupload")]
    public async Task<IActionResult> PackIt(List<IFormFile> files)
    {
        if (files == null || files.Count == 0)
        {
            return BadRequest("No files uploaded.");
        }

        return Ok(new { message = "Files received successfully." });
    }
}

前端代码

async function sendLogicFiles(fileHandles: FileSystemFileHandle[]) {
  try {
    const formData = new FormData()
    fileHandles.forEach(async (file, index) => {
      const fileHandle = fileHandles[index]
      const _file = await fileHandle.getFile()
      formData.append(`files[${index}]`, _file)
    })
    const response = await fetch('fileupload', {
      method: 'POST',
      body: formData,
    })
    if (!response.ok) {
      throw new Error('Network response was not ok ' + response.statusText)
    }
    const responseData = await response.json()
    console.log('Success:', responseData)
  } catch (error) {
    console.error('Error:', error)
  }
}

错误响应

{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "errors": {
        "files": [
            "The files field is required."
        ]
    },
    "traceId": "00-2073e137b176760a1c75cd95b8a542dc-6f64030c375117eb-00"
}

问题原因

  1. 异步循环导致FormData为空:前端用forEach结合async/await时,forEach不会等待异步操作完成,循环刚启动就直接执行了fetch请求,此时FormData里还没添加任何文件,后端自然接收不到。
  2. FormData键名格式问题:用files[${index}]作为键名,ASP.NET Core默认的模型绑定更适配重复使用同一个键名(比如多次formData.append('files', file)),带索引的格式反而可能导致绑定失败。

修复步骤

1. 修正前端异步逻辑

把forEach换成for...of循环,确保所有文件都读取并添加到FormData后再发送请求:

async function sendLogicFiles(fileHandles: FileSystemFileHandle[]) {
  try {
    const formData = new FormData()
    // 用for...of等待每个文件读取完成
    for (const fileHandle of fileHandles) {
      const _file = await fileHandle.getFile()
      // 直接用'files'作为键名,重复append
      formData.append('files', _file)
    }
    const response = await fetch('fileupload', {
      method: 'POST',
      body: formData,
    })
    if (!response.ok) {
      throw new Error('Network response was not ok ' + response.statusText)
    }
    const responseData = await response.json()
    console.log('Success:', responseData)
  } catch (error) {
    console.error('Error:', error)
  }
}

2. 可选:后端添加[FromForm]特性(新手友好)

虽然ASP.NET Core默认会从表单绑定,但显式加上[FromForm]能让代码更清晰,避免混淆:

public async Task<IActionResult> PackIt([FromForm] List<IFormFile> files)

验证

修改后重新测试,前端会先完成所有文件的读取和FormData的填充,再发送请求,后端就能正确接收到files列表,不会再触发必填校验。

实现方向说明

整体方向是对的:用FormData传递文件,后端用List<IFormFile>接收,符合ASP.NET Core文件上传的常规做法,只是前端异步逻辑和键名格式的小问题导致绑定失败。

内容的提问来源于stack exchange,提问作者CraZyDroiD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:13:19