我第一次尝试将文件从 Angular 组件上传到 ASPNET Core 网页,但根本无法正常工作。希望以下代码摘录足以显示正在发生的事情的要点。问题是,虽然我确认传递给 HttpClient 的 post 方法 (frmData) 的参数是有效的,但 ASPNet Core 操作方法从未看到它,并报告 IFormFile 始终为 null。
编辑:我之前曾尝试使用 multipart/form-data 作为内容类型,但我在 Kestrel 的内部给出了一个未处理的异常 .我现在意识到这是正确的方法,使用 json 内容类型是我的原始问题的根源。但我不知道从这里去哪里。我从一些谷歌搜索中看到,大约有\billion 个不同的原因导致该异常发生。
POST Executing endpoint 'JovenesA.Controllers.StudentssController.PostStudentGradesReport (JAWebAPI)' 04:55:38.4853 Info ControllerActionInvoker POST Route matched with {action = "PostStudentGradesReport", controller = "Becas"}. Executing action JovenesA.Controllers.BecasController.PostStudentGradesReport (JAWebAPI) 04:55:38.5032 Error DeveloperExceptionPageMiddleware POST An unhandled exception has occurred while executing the request. 04:55:38.5333 Info WebHost POST Request finished in 48.1225ms 500 text/html; charset=utf-8 04:55:38.5333 Info Kestrel Connection id "0HM4UHGE85O17", Request id "0HM4UHGE85O17:00000006": the application completed without reading the entire request body.
Any help would be greatly appreciated!
Angular Component:
fileEntry.file((file: File) => {
console.log('fileEntry relativePath: ' + currFile.relativePath);
console.log('filEntry.name: ', file.name);
console.log('filEntry.size: ', file.size);
const frmData = new FormData();
frmData.append(file.name, file);
this.studentData.uploadStudentGradesReport(file.name, frmData).subscribe(
() => {
this.successMessage = 'Changes were saved successfully.';
window.scrollTo(0, 0);
window.setTimeout(() => {
this.successMessage = '';
}, 3000);
},
(error) => {
this.errorMessage = error;
}
);
});
Angular 服务:
public uploadStudentGradesReport(filename: string, frmData: FormData): Observable<any> {
const url = this.WebApiPrefix + 'students/' + 'student-grades-report';
const headers = new HttpHeaders().set('Content-Type', 'application/json');
if (frmData) {
console.log('ready to post ' + url + ' filename: ' + filename + ' options ' + headers);
return this.http.post(url, frmData, { headers });
}
}
ASPNET 核心控件
// POST api/students/student-grades-report
[HttpPost("student-grades-report", Name = "PostStudentGradseReportRoute")]
//[ValidateAntiForgeryToken]
[ProducesResponseType(typeof(GradesGivenEntryApiResponse), 200)]
[ProducesResponseType(typeof(GradesGivenEntryApiResponse), 400)]
public async Task<ActionResult> PostStudentGradesReport([FromForm] IFormFile myFile)
{
_Logger.LogInformation("Post StudentGradesReport ");
if (myFile != null)
{
var totalSize = myFile.Length;
var fileBytes = new byte[myFile.Length];
如果有帮助,这是在 POST 请求中发送的数据
POST http://192.168.0.16:1099/api/students/student-grades-report HTTP/1.1 Host: 192.168.0.16:1099 Connection: keep-alive Content-Length: 13561 Accept: application/json, text/plain, */* DNT: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Content-Type: application/json Origin: http://localhost:3000 Referer: http://localhost:3000/ Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9,es-MX;q=0.8,es;q=0.7 ------WebKitFormBoundaryBVuZ7IbkjtQAKQ0a Content-Disposition: form-data; name="test1.PNG"; filename="test1.PNG" Content-Type: image/png PNG [ binary contents of the image file ] ------WebKitFormBoundaryBVuZ7IbkjtQAKQ0a--
最佳答案
您将文件作为表单数据发送,因此您需要指定正确的内容类型 header 。目前您在 Content-Type
header 中发送 application/json
。即使在调用 API 时也是如此,一开始可能会造成混淆,这是可以理解的。在这种情况下,正确的内容类型是 multipart/form-data
。您的 API 没有看到 IFormFile
,因为它认为请求是 JSON。我已经使用正确的内容类型 header 值修改了您的 Angular 代码。
编辑: 结果表明,手动指定 Content-Type
header 将导致不会在 header 值中自动设置边界值。相反,简单的解决方案是不要自己添加 header ,这将导致自动设置正确的内容类型和边界值。如果您自己设置 header ,则还必须设置边界值。对于大多数情况,将其保留为默认值可能是最好的解决方案。指向指出这一点的问题/答案的链接。
FormData how to get or set boundary in multipart/form-data - Angular
public uploadStudentGradesReport(filename: string, frmData: FormData): Observable<any> {
const url = this.WebApiPrefix + 'students/' + 'student-grades-report';
const headers = new HttpHeaders().set('Content-Type', 'multipart/form-data');
if (frmData) {
console.log('ready to post ' + url + ' filename: ' + filename + ' options ' + headers);
return this.http.post(url, frmData, { headers });
}
}
您还可以注意您提供的 HTTP 请求上的内容配置,它显示表单数据以及附加文件的类型。希望这可以帮助。我没有启动 Angular 项目来测试您的代码,但内容类型应该可以解决您的问题。
编辑:我注意到您使用文件名作为文件表单字段的键。您需要为表单字段使用诸如"file"之类的键,该键应与 Controller 代码中的参数名称相匹配。您可以在 Controller 代码中获取文件的实际文件名,键仅指示文件附加到哪个表单字段。示例
frmData.append('file', file);
然后为您的 Controller 操作
public async Task<IActionResult> PostStudentGradesReport([FromForm] IFormFile file)
{
if (file.Length <= 0 || file.ContentType is null) return BadRequest();
var actualFileName = file.FileName;
using (var stream = file.OpenReadStream())
{
// Process file...
}
return Ok();
}
关于angular - 从 Angular 上传文件到 ASP.NET Core,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65256628/