Angular 10向ASP.NET Core 3.1 WebAPI上传文件失败求助
解决Angular 10向ASP.NET Core 3.1 WebAPI上传文件失败的问题
我帮你分析下这个问题——ASP.NET Core 3.1和2.2在表单数据(尤其是multipart/form-data类型的文件上传请求)的处理逻辑上有不少调整,再加上你代码里的一些小疏漏,导致之前在2.2能正常运行的代码到3.1就失效了。下面一步步帮你解决:
1. 先修复ASP.NET Core 3.1的请求配置
ASP.NET Core 3.1默认收紧了请求大小的限制,并且对Multipart表单的处理需要显式配置。你需要在Startup.cs的ConfigureServices方法里添加以下配置:
public void ConfigureServices(IServiceCollection services) { // 调整表单请求的大小限制,避免大文件上传被拦截 services.Configure<FormOptions>(options => { options.MultipartBodyLengthLimit = 10485760; // 这里设为10MB,你可以根据需求调整更大的值 options.ValueLengthLimit = int.MaxValue; options.MultipartHeadersLengthLimit = int.MaxValue; }); // 如果你需要兼容旧的JSON序列化行为(比如之前用Newtonsoft.Json),记得加上这一行 services.AddControllers().AddNewtonsoftJson(); }
2. 修复WebAPI代码里的逻辑错误
你的WebAPI代码里有几个明显的问题,会导致报错或数据异常:
- 重复赋值
DateOfBirth:你先把caseModel.DateOfBirth赋值为请求里的DateOfBirth字段,之后又错误地用DateOfJoining覆盖了它,这不仅会导致数据错误,还可能因为日期格式问题抛出异常:
改成正确的赋值:// 原来的错误代码 caseModel.DateOfBirth = Convert.ToDateTime(httpRequest["DateOfBirth"].ToString()); // ... caseModel.DateOfBirth = Convert.ToDateTime(httpRequest["DateOfJoining"].ToString());caseModel.DateOfBirth = Convert.ToDateTime(httpRequest["DateOfBirth"].ToString()); // ... caseModel.DateOfJoining = Convert.ToDateTime(httpRequest["DateOfJoining"].ToString()); - 未处理缺失的表单参数:你代码里尝试获取
httpRequest["type"]和httpRequest["documentTitle"],但你的Angular代码并没有把这两个参数添加到FormData里,这会导致空值甚至报错。要么在Angular里补充这些参数,要么在WebAPI里做空值判断:var docType = httpRequest.ContainsKey("type") ? httpRequest["type"].ToString() : string.Empty; var docTitle = httpRequest.ContainsKey("documentTitle") ? httpRequest["documentTitle"].ToString() : string.Empty; - 文件保存路径的问题:你用了
ContentRootPath(项目根目录)来保存文件,如果你想让上传的文件能通过Web访问,应该改用WebRootPath(wwwroot目录),否则文件会存在项目的非Web可访问目录下:string folderName = "UploadedFiles"; string projectRootPath = _webHostEnvironment.WebRootPath; // 替换原来的ContentRootPath var docSavePath = Path.Combine(projectRootPath, folderName);
3. 完善Angular端的FormData构造
你的Angular代码只添加了ApplicantName和文件,没有把WebAPI需要的其他表单字段(比如FatherOrSpouseName、DateOfBirth等)添加到FormData里,这会导致WebAPI里获取这些值时为空,引发异常。修改saveCase方法:
saveCase() { if (this.caseForm.valid) { const formData = new FormData(); // 批量添加所有表单字段 Object.keys(this.caseForm.value).forEach(key => { formData.append(key, this.caseForm.value[key]); }); // 添加选中的文件(先判断是否有文件) if (this.selectedFile) { formData.append("file", this.selectedFile, this.selectedFile.name); } // 如果WebAPI需要type和documentTitle,记得在这里添加 // formData.append("type", "身份证"); // 示例值,根据你的业务调整 // formData.append("documentTitle", "申请人身份证"); this.http.post("https://localhost:44343/api/Case/UploadDocument", formData, { reportProgress: true, observe: 'events' }) .subscribe(event => { if (event.type === HttpEventType.UploadProgress) { console.log("Upload Progress: " + Math.round(event.loaded / event.total * 100) + '%') } else if (event.type === HttpEventType.Response) { console.log(event); this.toastr.success('Case', 'Case Created Successfully'); this.resetCaseForm(); // 把重置表单移到成功回调里,避免失败也重置 } }, err => { console.error(err); this.toastr.error('Error', 'Failed to upload case and document'); }); } }
另外,确保你的onFileSelected方法正确设置选中的文件:
selectedFile: File | null = null; onFileSelected(event: any) { this.selectedFile = event.target.files[0]; }
4. 调试小技巧
如果还是有问题,可以用这两个方法排查:
- 在WebAPI的
UploadDocument方法开头添加日志,查看接收到的表单数据和文件情况:foreach (var key in httpRequest.Keys) { _logger.LogInformation($"{key}: {httpRequest[key]}"); } _logger.LogInformation($"Received files count: {httpRequest.Files.Count}"); - 在浏览器开发者工具的「Network」标签里,查看上传请求的「Form Data」部分,确认所有字段和文件都正确发送了。
内容的提问来源于stack exchange,提问作者GOPAL SHARMA
相关产品推荐
相关产品推荐

