Unggah file dari Angular ke ASP.NET Core
Untuk pertama kalinya saya mencoba mengunggah file dari komponen Angular ke halaman web ASPNET Core, dan tidak bisa membuatnya berfungsi. Semoga kutipan kode berikut cukup untuk menunjukkan hal-hal penting dari apa yang sedang terjadi. Masalahnya adalah meskipun saya mengonfirmasi bahwa parameter yang diteruskan ke metode posting HttpClient (frmData) valid, metode tindakan ASPNet Core tidak pernah melihatnya, dan melaporkan bahwa IFormFile selalu null.
EDIT: Saya sebelumnya mencoba menggunakan multipart / form-data sebagai jenis konten tetapi saya memberikan pengecualian yang tidak tertangani di nyali Kestrel. Saya sekarang menyadari bahwa ini adalah cara yang benar untuk melakukannya, dan menggunakan tipe konten json adalah sumber masalah ASLI saya. Tapi saya tidak tahu harus pergi ke mana setelah ini. Saya melihat dari beberapa googling ada sekitar \ miliar penyebab berbeda untuk pengecualian itu terjadi.
POST Executing endpoint 'JovenesA.Controllers.StudentssController.PostStudentGradesReport (JAWebAPI)' 04: 55: 38.4853 Info ControllerActionInvoker Rute POST cocok dengan {action = "PostStudentGradesReport", controller = "Becas"}. Menjalankan tindakan JovenesA.Controllers.BecasController.PostStudentGradesReport (JAWebAPI) 04: 55: 38.5032 Error DeveloperExceptionPageMiddleware POST Pengecualian tidak tertangani terjadi saat menjalankan permintaan. 04: 55: 38.5333 Info WebHost Permintaan POST selesai dalam teks / html 48,1225ms 500; charset = utf-8 04: 55: 38.5333 Info Kestrel ID koneksi "0HM4UHGE85O17", ID permintaan "0HM4UHGE85O17: 00000006": aplikasi diselesaikan tanpa membaca seluruh isi permintaan.
Bantuan apa pun akan sangat dihargai!
Komponen Sudut:
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;
}
);
});
Layanan Sudut:
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 });
}
}
Kontrol Inti 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];
Jika membantu, berikut adalah data yang dikirim dalam permintaan POST
POST http://192.168.0.16:1099/api/students/student-grades-report HTTP / 1.1 Tuan rumah: 192.168.0.16:1099 Koneksi: tetap hidup Panjang Konten: 13561 Terima: application / json, text / plain, * / * DNT: 1 Agen Pengguna: Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, seperti Gecko) Chrome / 87.0.4280.88 Safari / 537.36 Jenis Konten: application / json Asal: http: // localhost: 3000 Perujuk: http: // localhost: 3000 / Terima-Enkode: gzip, deflate Terima-Bahasa: en-US, en; q = 0.9, es-MX; q = 0.8, es; q = 0.7 ------ WebKitFormBoundaryBVuZ7IbkjtQAKQ0a Isi-Disposisi: form-data; name = "test1.PNG"; nama file = "test1.PNG" Jenis-Konten: image / png PNG [konten biner dari file gambar] ------ WebKitFormBoundaryBVuZ7IbkjtQAKQ0a--
Jawaban
Anda mengirim file sebagai data formulir, jadi Anda perlu menentukan header tipe konten yang benar. Saat ini Anda mengirimkan application/json
di Content-Type
header. Ini benar bahkan saat memanggil API, yang awalnya bisa membingungkan. Jenis konten yang benar dalam kasus ini adalah multipart/form-data
. API Anda tidak dapat melihat IFormFile
karena mengira permintaannya adalah JSON. Saya telah memodifikasi kode Angular Anda dengan nilai header tipe konten yang benar.
Edit: Ternyata menentukan Content-Type
header secara manual akan menyebabkan nilai batas tidak disetel secara otomatis di nilai header. Sebagai gantinya, solusi sederhananya adalah dengan tidak menambahkan tajuk sendiri, yang akan menghasilkan tipe konten yang tepat dan nilai batas untuk ditetapkan secara otomatis. Jika Anda menyetel tajuk sendiri, Anda juga harus menyetel nilai batasnya juga. Untuk sebagian besar situasi, membiarkannya default mungkin merupakan solusi terbaik. Tautan ke pertanyaan / jawaban yang menunjukkan hal ini. FormData cara mendapatkan atau mengatur batas dalam 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 });
}
}
Anda juga dapat mencatat disposisi konten yang ada pada permintaan HTTP yang Anda berikan, yang menunjukkan data formulir bersama dengan jenis file yang dilampirkan. Semoga ini membantu. Saya tidak menjalankan proyek Angular untuk menguji kode Anda tetapi tipe konten harus memperbaiki masalah Anda.
Edit : Saya perhatikan bahwa Anda menggunakan nama file sebagai kunci untuk bidang formulir dengan file tersebut. Anda perlu menggunakan kunci seperti hanya 'file' untuk bidang formulir, yang harus cocok dengan nama parameter dalam kode pengontrol Anda. Anda bisa mendapatkan nama file sebenarnya dari file dalam kode pengontrol Anda, kuncinya hanya menunjukkan bidang formulir mana file tersebut dilampirkan. Contoh
frmData.append('file', file);
Dan kemudian untuk tindakan pengontrol Anda
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();
}
Saya tidak dapat menjamin bahwa ini akan berhasil, tetapi Anda dapat mencoba menggunakan HttpRequest Angular. Jadi dalam layanan sudut Anda, coba ini:
const request = new HttpRequest (
'POST',
url, // http://localhost/your_endpoint
frmData,
{ withCredentials: false }
);
return this.http.request(request);
Perhatikan juga bahwa Anda tidak boleh melakukan validasi data dalam fungsi yang memanggil Api backend. Apa fungsi Anda akan kembali jika if(frmData)
salah?