Datei Upload mit ASP.NET Core

Datei Upload gehört (e) zu den Standard Anforderungen an eine Web Site. Ein Bild hochladen, ein Excel Report. Entsprechend einfach ist das mit ASP.NET Webforms. Dazu haben die Redmonder Entwickler mitgedacht und einen spezielle Ordner App_Data als Speicherort vorgesehen. Der Webserver IIS schützt automatisch (durch Konfiguration) dort liegende Daten vor Download oder Ausführung. Nichts davon ist in ASP.NET Core zu finden. Wenn man im Web sucht, findet man zig völlig unterschiedliche Lösungsvorschläge u.a. mit einem Fileprovider den man in die Middleware konfigurieren muss- absurd.

Datei speichern

Lösen wir das erste Problem. Das Verzeichnis app_data kann man noch anlegen. Der Logik und Konvention von Razor folgend im Projektverzeichnis wwwroot. Der Ordner für static Files. Meine Tests mit IIS und Azure App Service haben ergeben, das dort nach wie vor der Zugriff per Browser Url nicht möglich ist. Mit Webforms würde man Server.Mappath(“app_data”) nutzen um den physikalischen Pfad auf dem Zielsystem dynamisch auslesen zu können. Ein derartiges Server Helper Objekt existiert in .NET core nicht.

   1:  var pfad = Path.Combine(
   2:                       Directory.GetCurrentDirectory(),
   3:                        @"wwwroot\app_data");

 

Formular konventionell

Schon  immer muss ein im HTML Code der Datei Upload Form Post mit passenden Encoding versehen sein.

   1:  <form method="post" enctype="multipart/form-data">
   2:      <input type="file" name="Upload" />
   3:      <button>upload</button>
   4:  </form>

Um dann im Server Code die Datei und seine Eigenschaften verarbeiten zu können, kann auch quasi schon immer über das  Request Objekt (wie bei Webforms auch) auf die Inhalte des Form Posts zugegriffen werden.

   1:    var formFile = HttpContext.Request.Form.Files[0]; 

Neu ist in ASP.NET Core der Speichertyp IFormFile der u.a. den Dateinamen (Filename) und die Datei als Stream beinhaltet.

Formular per Binding

Die ASP.NET Core Razor View Engine soll die Dinge einfacher machen und kommt damit an manchen Stellen an den Komfort von Webforms heran. Dazu gehört das Databinding, das z.B. die Input Boxen automatisch nach einem Postback gefüllt hält. Ähnlich dem ASP.NET Webforms Modelbinding wird ein Model als Property in der Razor PageModel Klasse deklariert und mit einem Attribut als Bindbar erklärt. Im Upload Beispiel minimalistisch die Variable Upload

   1:  public class DemoUploadModel : PageModel
   2:      {
   3:          [BindProperty]
   4:          public IFormFile Upload { get; set; }

 

Das Formular muss ein wenig geändert werden. Das DataBinding wird über die Taghelpers aktiviert. Diese müssen (Zeile 1) eingebunden werden. Der Name des Input wird entfernt (Zeile 5) und der Tag Helper asp-for mit dem Property Namen Upload eingebunden. Zur Laufzeit wird im HTMl ein ident benanntes HTML Input erzeugt.

   1:  @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
   2:  <html>
   3:  <body>
   4:      <form method="post" enctype="multipart/form-data">
   5:          <input type="file" asp-for="Upload" />

 

Die Razor Pages sind wesentlich einfacher als die MVC Controller Klassen. Das Routing in die Actions, Methoden erfolgt automatisch, wenn man sich an die vorgegeben Konventionen hält. Entsprechend der HTTP Kommandos mit dem Prefix On. Hier also OnPost. Der Rest ist einfacher Datei Zugriff per Stream.

   1:  public void OnPost()
   2:    {
   3:     var pfad = Path.Combine(
   4:                   Directory.GetCurrentDirectory(),
   5:                   @"wwwroot\app_data");
   6:      using (var fileStream = new FileStream(pfad+"/"+Upload.FileName, FileMode.Create))
   7:              {
   8:                  Upload.CopyToAsync(fileStream);
   9:              }
  10:   }
Kommentare sind geschlossen