Angular'dan ASP.NET Core'a Dosya Yükleme
İlk defa bir Angular bileşenden bir ASPNET Core web sayfasına bir dosya yüklemeye çalışıyorum ve onu çalıştıramıyorum. Umarım aşağıdaki kod alıntıları, neler olup bittiğinin temellerini göstermek için yeterli olacaktır. Sorun şu ki, HttpClient'in post yöntemine (frmData) geçirilen parametrenin geçerli olduğunu doğrulamama rağmen, ASPNet Core eylem yöntemi bunu asla görmez ve IFormFile'ın her zaman boş olduğunu bildirir.
DÜZENLEME: Daha önce, içerik türü olarak multipart / form-data kullanmayı denedim, ancak Kestrel'in bağırsaklarında işlenmemiş bir istisna verdim. Bunu yapmanın doğru yolunun bu olduğunu şimdi anlıyorum ve ORİJİNAL problemimin kaynağı json içerik türü kullanmaktı. Ama buradan nereye gideceğimi bilmiyorum. Bazı Google'lardan görüyorum ki bu istisnanın meydana gelmesi için yaklaşık bir milyar farklı neden var.
POST Yürütme uç noktası 'JovenesA.Controllers.StudentssController.PostStudentGradesReport (JAWebAPI)'
04: 55: 38.4853 Bilgi DenetleyicisiActionInvoker
POST Rotası {action = "PostStudentGradesReport", controller = "Becas"} ile eşleşti. JovenesA.Controllers.BecasController.PostStudentGradesReport (JAWebAPI) eylemini yürütme
04: 55: 38.5032 DeveloperExceptionPageMiddleware Hatası
POST İstek yürütülürken işlenmeyen bir istisna oluştu.
04: 55: 38.5333 Bilgi WebHost
POST İsteği 48.1225ms 500 text / html'de tamamlandı; karakter kümesi = utf-8
04: 55: 38.5333 Bilgi Kestrel
Bağlantı kimliği "0HM4UHGE85O17", İstek kimliği "0HM4UHGE85O17: 00000006": uygulama, tüm istek gövdesini okumadan tamamlandı.
Herhangi bir yardım çok takdir edilecektir!
Açısal Bileşen:
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;
}
);
});
Açısal Hizmet:
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 Çekirdek Denetimi
// 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];
Yardımcı olursa, POST isteğinde gönderilen veriler burada
POST http://192.168.0.16:1099/api/students/student-grades-report HTTP / 1.1 Ana Bilgisayar: 192.168.0.16:1099 Bağlantı: canlı tutma İçerik Uzunluğu: 13561 Kabul et: application / json, text / plain, * / * DNT: 1 Kullanıcı Aracısı: Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, Gecko gibi) Chrome / 87.0.4280.88 Safari / 537.36 İçerik Türü: uygulama / json Menşei: http: // localhost: 3000 Başvuran: 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 İçerik Eğilimi: biçim verileri; name = "test1.PNG"; filename = "test1.PNG" İçerik Türü: resim / png PNG [görüntü dosyasının ikili içeriği] ------ WebKitFormBoundaryBVuZ7IbkjtQAKQ0a--
Yanıtlar
Dosyayı form verileri olarak gönderiyorsunuz, bu nedenle doğru içerik türü başlığını belirtmeniz gerekiyor. Şu anda senin gönderme application/jsoniçinde Content-Typebaşlığındaki. Bu, ilk başta anlaşılır şekilde kafa karıştırıcı olabilecek bir API çağırırken bile geçerlidir. Bu durumda doğru içerik türü multipart/form-data. IFormFileAPI'niz, isteğin JSON olduğunu düşündüğü için öğesini görmüyor . Açısal kodunuzu doğru içerik türü başlık değeri ile değiştirdim.
Düzenleme: Bir Content-Typebaşlığı manuel olarak belirlemenin, başlık değerinde sınır değerlerinin otomatik olarak ayarlanmamasına neden olacağı ortaya çıkar. Bunun yerine basit çözüm, başlığı kendiniz eklememektir, bu da uygun içerik türü ve sınır değerlerinin otomatik olarak ayarlanmasına neden olur. Başlığı kendiniz ayarlarsanız, sınır değerlerini de ayarlamanız gerekecektir. Çoğu durumda, varsayılan olarak bırakmak muhtemelen en iyi çözümdür. Buna işaret eden soru / cevap bağlantısı. FormData çok parçalı / form verilerinde sınır nasıl alınır veya ayarlanır - Açısal
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 });
}
}
Ayrıca, sağladığınız HTTP isteğindeki, form verilerini ekli dosya türüyle birlikte gösteren içerik düzenini de not edebilirsiniz. Bu yardımcı olur umarım. Kodunuzu test etmek için bir Angular projesi başlatmadım, ancak içerik türü sorununuzu çözmeli.
Düzenle : Dosyadaki form alanı için anahtar olarak dosya adını kullandığınızı fark ettim. Denetleyici kodunuzdaki parametrenin adıyla eşleşmesi gereken form alanı için yalnızca 'dosya' gibi bir anahtar kullanmanız gerekir. Denetleyici kodunuz içinde dosyanın gerçek dosya adını alabilirsiniz, anahtar basitçe dosyaların hangi form alanına eklendiğini gösterir. Misal
frmData.append('file', file);
Ve sonra denetleyici eyleminiz için
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();
}
Bunun işe yarayacağını garanti edemem, ancak Angular'ın HttpRequest'ini kullanmayı deneyebilirsiniz. Yani açısal hizmetinizde şunu deneyin:
const request = new HttpRequest (
'POST',
url, // http://localhost/your_endpoint
frmData,
{ withCredentials: false }
);
return this.http.request(request);
Ayrıca, arka uç API'sini çağıran işlevde veri doğrulaması yapmamanız gerektiğini unutmayın. Yanlışsa işleviniz ne döndürecektir if(frmData)?