Angular에서 ASP.NET Core로 파일 업로드
처음으로 Angular 구성 요소에서 ASPNET Core 웹 페이지로 파일을 업로드하려고하는데 작동하지 않습니다. 바라건대 다음 코드 발췌 부분이 무슨 일이 일어나고 있는지의 핵심을 보여주기에 충분할 것입니다. 문제는 HttpClient의 post 메서드 (frmData)에 전달 된 매개 변수가 유효한지 확인했지만 ASPNet Core 작업 메서드가이 매개 변수를 보지 못하고 IFormFile이 항상 null이라고보고한다는 것입니다.
편집 : 이전에 콘텐츠 유형으로 multipart / form-data를 사용하려고 시도했지만 Kestrel의 용기에서 처리되지 않은 예외를 제공했습니다. 이것이 올바른 방법이며 json 콘텐츠 유형을 사용하는 것이 내 원래 문제의 원인이라는 것을 이제 깨달았습니다. 하지만 여기서 어디로 가야할지 모르겠습니다. 일부 인터넷 검색에서 해당 예외가 발생하는 데 약 10 억 가지 다른 원인이 있음을 알 수 있습니다.
POST 실행 끝점 'JovenesA.Controllers.StudentssController.PostStudentGradesReport (JAWebAPI)' 04 : 55 : 38.4853 정보 컨트롤러 ActionInvoker {action = "PostStudentGradesReport", 컨트롤러 = "Becas"}와 일치하는 POST 경로. JovenesA.Controllers.BecasController.PostStudentGradesReport (JAWebAPI) 조치 실행 04 : 55 : 38.5032 오류 DeveloperExceptionPageMiddleware POST 요청을 실행하는 동안 처리되지 않은 예외가 발생했습니다. 04 : 55 : 38.5333 정보 웹 호스트 POST 요청은 48.1225ms 500 text / html로 완료되었습니다. charset = utf-8 04 : 55 : 38.5333 정보 Kestrel 연결 ID "0HM4UHGE85O17", 요청 ID "0HM4UHGE85O17 : 00000006": 전체 요청 본문을 읽지 않고 애플리케이션이 완료되었습니다.
어떤 도움이라도 대단히 감사하겠습니다!
각도 구성 요소 :
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;
}
);
});
각도 서비스 :
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 Core 컨트롤
// 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 호스트 : 192.168.0.16:1099 연결 : 연결 유지 콘텐츠 길이 : 13561 수락 : application / json, text / plain, * / * DNT : 1 사용자 에이전트 : Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 87.0.4280.88 Safari / 537.36 콘텐츠 유형 : application / json 출처 : http : // localhost : 3000 참조 자 : 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 콘텐츠 처리 : 양식 데이터; name = "test1.PNG"; filename = "test1.PNG" 콘텐츠 유형 : image / png PNG [이미지 파일의 바이너리 내용] ------ WebKitFormBoundaryBVuZ7IbkjtQAKQ0a--
답변
파일을 양식 데이터로 보내므로 올바른 콘텐츠 유형 헤더를 지정해야합니다. 현재 헤더에 보내는 application/json
중 Content-Type
입니다. API를 호출하는 경우에도 마찬가지이며 처음에는 이해하기 어려울 수 있습니다. 이 경우 올바른 콘텐츠 유형은 multipart/form-data
입니다. IFormFile
요청이 JSON이라고 생각하기 때문에 API에이 표시되지 않습니다 . 올바른 콘텐츠 유형 헤더 값으로 Angular 코드를 수정했습니다.
편집 :Content-Type
헤더 를 수동으로 지정 하면 경계 값이 헤더 값에 자동으로 설정되지 않는 것으로 나타났습니다. 대신 간단한 해결책은 헤더를 직접 추가하지 않는 것입니다. 그러면 적절한 콘텐츠 유형 및 경계 값이 자동으로 설정됩니다. 헤더를 직접 설정하는 경우 경계 값도 설정해야합니다. 대부분의 경우 기본값으로 두는 것이 가장 좋은 해결책 일 것입니다. 이를 지적하는 질문 / 답변 링크. FormData 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 프로젝트를 시작하지는 않았지만 콘텐츠 유형이 문제를 해결해야합니다.
편집 : 파일이있는 양식 필드의 키로 파일 이름을 사용하고 있음을 확인했습니다. 컨트롤러 코드의 매개 변수 이름과 일치해야하는 양식 필드에 '파일'과 같은 키를 사용해야합니다. 컨트롤러 코드 내에서 파일의 실제 파일 이름을 얻을 수 있으며 키는 단순히 파일이 첨부 된 양식 필드를 나타냅니다. 예
frmData.append('file', file);
그런 다음 컨트롤러 작업을 위해
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의 HttpRequest를 사용해 볼 수 있습니다. 따라서 각도 서비스에서 다음을 시도하십시오.
const request = new HttpRequest (
'POST',
url, // http://localhost/your_endpoint
frmData,
{ withCredentials: false }
);
return this.http.request(request);
또한 백엔드 API를 호출하는 함수에서 데이터 유효성 검사를 수행하면 안됩니다. if(frmData)
거짓 이면 함수가 무엇을 반환 합니까?