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" }
问题原因
- 异步循环导致FormData为空:前端用
forEach结合async/await时,forEach不会等待异步操作完成,循环刚启动就直接执行了fetch请求,此时FormData里还没添加任何文件,后端自然接收不到。 - 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
相关产品推荐
相关产品推荐

