Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Dateiupload mit ASP.NET

Geschrieben von: Christoph Wille
Kategorie: ASP.NET

Etwas das unter ASP ohne Fremdkomponente nicht vernünftig möglich war ist das Uploaden von Dateien auf einen Webserver, obwohl die Verwendungsmöglichkeiten dieses Features vom Content-Managementsystem bis zu einem Kostenvoranschlagsservice für Übersetzungen (basierend auf dem Inhalt von upgeloadeten Dateien) reichen kann. Natürlich sind das nur zwei von vielen Anwendungsmöglichkeiten.

Wie gesagt, unter ASP benötigt man Fremdkomponenten, um mittels ASP Dateien am Webserver entgegennehmen zu können. ASP.NET bietet diese Funktionalität mit einer HTML Control names HtmlInputFile, die sich von der bereits bekannten INPUT TYPE=FILE im groben nur durch das RUNAT=SERVER Tag unterscheidet. Aber sie ist fixer Bestandteil des Produkts, managed den Upload für Sie, und verhält sich am Browser wie die normale Control die Sie bereits kennen.

In diesem Artikel stelle ich zwei Anwendungsfälle des Dateiuploads vor:

  • Upload in eine Datei
  • Upload und direkte Weiterverwendung der Daten

Bei ersterem Ansatz handelt es sich um die einfachste Lösung, der zweite demonstriert ein sehr flexibles Konzept wie man die Daten des Uploads selbst in Empfang nehmen und weiterverarbeiten kann.

Voraussetzung um den Sourcecode dieses Artikels verwenden zu können ist eine Installation des Microsoft .NET Framework SDK's auf einem Webserver. Weiters setze ich voraus, daß der Leser die Programmiersprache C# zu einem gewissen Grad beherrscht - es finden sich etliche Artikel auf diesem Server, um das notwendige Wissen zu erlernen.

Upload in eine Datei

Sehen Sie sich den nachfolgenden Screenshot an - solche Beispiele dürften Ihnen vom Dateiupload unter ASP auch bereits bekannt sein.

Obwohl es von "außen" nicht viel anders aussieht, so passiert unter der Haube doch etwas deutlich anderes als wir es von ASP gewohnt sind. Dazu werden wir jetzt den Sourcecode genauer unter die Lupe nehmen (uploadNsave.aspx):

<% @Page Language="C#" %>
<html>
<head>
  <title>Dateiupload in ASP.NET</title>
</head>
<body bgcolor="#ffffff" style="font:8pt verdana;">
<script language="C#" runat="server">
void btnUploadTheFile_Click(object Source, EventArgs evArgs) 
{
  string strFileNameOnServer = txtServername.Value;
  string strBaseLocation = "c:\\temp\\";
  
  if ("" == strFileNameOnServer) 
  {
    txtOutput.InnerHtml = "Fehler - es muß ein Dateiname angegeben werden.";
    return;
  }

  if (null != uplTheFile.PostedFile) 
  {
    try 
    {
      uplTheFile.PostedFile.SaveAs(strBaseLocation+strFileNameOnServer);
      txtOutput.InnerHtml = "Datei erfolgreich nach <b>" + 
        strBaseLocation+strFileNameOnServer+"</b> upgeloadet";
    }
    catch (Exception e) 
    {
      txtOutput.InnerHtml = "Fehler beim Speichern von <b>" + 
        strBaseLocation+strFileNameOnServer+"</b><br>"+ e.ToString();
    }
  }
}
</script>

<table>
<form enctype="multipart/form-data" runat="server">
<tr>
  <td>Datei ausw&auml;hlen:</td>
  <td><input id="uplTheFile" type=file runat="server"></td>
</tr>
<tr>
  <td>Name am Server:</td>
  <td><input id="txtServername" type="text" runat="server"></td>
</tr>
<tr>
  <td colspan="2">
  <input type=button id="btnUploadTheFile" value="Speichern" 
                    OnServerClick="btnUploadTheFile_Click" runat="server">
  </td>
</tr>
</form>
</table>
    
<span id=txtOutput style="font: 8pt verdana;" runat="server" />

</body>
</html>

Betrachten wir für den Anfang nur das Formular, das die Datei (und den Namen, den sie am Server erhalten soll) an den Server schickt. Da wir gemischte Daten schicken, ist der enctype auf multipart/form-data gesetzt. Das ist noch nichts Neues. Das Einzige, das auf ASP.NET hinweist ist daß das Form am Server ausgeführt wird (RUNAT=SERVER).

In diesem Formular verwende ich im Gegensatz zum Artikel On-the-fly Generierung von Graphiken keine Web Controls, sondern HTML Controls - deswegen sieht es auch sehr vertraut aus. Allerdings würde man unter ASP sicher nicht das finden:

<input type=button id="btnUploadTheFile" value="Speichern" 
   OnServerClick="btnUploadTheFile_Click" runat="server">

Der Klick auf den Button löst am Server ein Event aus, das in der Funktion btnUploadTheFileFile_Click abgehandelt wird. Und somit sind wir beim Code, der notwendig ist, um eine Datei am Server erfolgreich abzuspeichern:

if (null != uplTheFile.PostedFile) 
{
  try 
  {
    uplTheFile.PostedFile.SaveAs("c:\\temp\\file.bin");
    txtOutput.InnerHtml = "Datei erfolgreich upgeloadet";
  }
  catch (Exception e) 
  {
    txtOutput.InnerHtml = "Fehler beim Speichern<br>"+ e.ToString();
  }
}

Das ist zwar nicht exakt der Sourcecode aus dem Beispiel, allerdings fehlt nur das "Rundherum" für die Namensvergabe am Server - der Fileupload funktioniert hier ebenso. Also was passiert? Die if Abfrage überprüft, ob eine Datei gepostet wurde, indem sie die Eigenschaft PostedFile gegen null vergleicht. Wird eine Datei upgeloadet, so hält diese Eigenschaft eine gültige Referenz auf ein Objekt vom Typ HttpPostedFile, und ist somit verschieden von null.

Nach diesem Sicherheitscheck bleibt uns "nur noch" die Datei zu speichern - ein simpler Aufruf der Funktion SaveAs auf dem Objekt HttpPostedFile erledigt alles für uns. Sollte etwas schiefgehen, wird unser Code darüber mit einer Exception benachrichtigt. So einfach ist es in ASP.NET eine Datei auf den Webserver zu laden.

Der Code im Beispiel selbst differiert nur dahingehend, daß die Datei einen benutzergewählten Namen erhalten kann. Dadurch ist er zwar etwas länger, aber bereits sehr flexibel. Der Weiterverwendung und Erweiterung in eigenen Projekten steht nichts im Wege.

Upload und direkte Weiterverwendung der Daten

So nett und schön das einfache Speichern der upgeloadeten Datei in eine Datei am Server auch sein kein, so oft möchte man mit den upgeloadeten Daten (den Bits) sofort wieder weiterarbeiten - ohne den Umweg in eine Datei. Anwendungsfälle wären etwa die Daten in die Datenbank zu speichern, die Daten zu parsen, oder irgendeine andere Bearbeitung durchzuführen.

Auch in diesem Fall läßt uns ASP.NET und das .NET Framework nicht im Stich. Anstatt die Kontrolle mit der SaveAs Funktion aus der Hand zu geben, kann man direkten Zugriff auf den Stream der upgeloadeten Daten bekommen und mit diesen sofort weiterarbeiten - während der Upload passiert.

Das Beispiel, das ich zu Demonstrationszwecken gebastelt habe, erfüllt derzeit nur einen Zweck: die upgeloadeten Daten werden aus dem Stream ausgelesen und in einer Stringvariablen zwischengespeichert - um dann einfach an den Client zurückgeschickt zu werden. Für Textuploads mag das bereits sinnvoll sein, bei binären Uploads (Bilder zum Beispiel) ist der Output nicht gerade überwältigend:

Der vorige Screenshot zeigt, daß mein Sourcecode (uploadNdump.aspx) auch mit binären Daten korrekt umgehen kann. Dies erreicht ich durch eine Zwangsumkonvertierung auf ASCII. Die Details dazu können Sie dem Sourcecode und der folgenden Beschreibung entnehmen.

<% @Page Language="C#" %>
<% @Import Namespace="System.IO" %>
<% @Import Namespace="System.Text" %>
<html>
<head>
  <title>Dateiupload in ASP.NET</title>
</head>
<body bgcolor="#ffffff" style="font:8pt verdana;">
<script language="C#" runat="server">
void btnUploadTheFile_Click(object Source, EventArgs evArgs) 
{
  if (null != uplTheFile.PostedFile) 
  {
    try 
    {
      const int BUFFER_SIZE = 255;
      int nBytesRead = 0;
      Byte[] Buffer = new Byte[BUFFER_SIZE];
      StringBuilder strUploadedContent = new StringBuilder("");
      
      Stream theStream = uplTheFile.PostedFile.InputStream;
      nBytesRead = theStream.Read(Buffer, 0, BUFFER_SIZE);
      
      while (0 != nBytesRead)
      {
        strUploadedContent.Append(
                Encoding.ASCII.GetString(Buffer,0,nBytesRead));
        nBytesRead = theStream.Read(Buffer,0,BUFFER_SIZE);
      }
      
      txtOutput.InnerHtml = strUploadedContent.ToString();
    }
    catch (Exception e) 
    {
      txtOutput.InnerHtml = "Fehler beim Speichern von <b>" + 
        uplTheFile.PostedFile.FileName + "</b><br>"+ e.ToString();
    }
  }
}
</script>

<table>
<form enctype="multipart/form-data" runat="server">
<tr>
  <td>Datei ausw&auml;hlen:</td>
  <td><input id="uplTheFile" type=file runat="server"></td>
</tr>
<tr>
  <td colspan="2">
  <input type=button id="btnUploadTheFile" value="Speichern" 
                    OnServerClick="btnUploadTheFile_Click" runat="server">
  </td>
</tr>
</form>
</table>
    
<span id=txtOutput style="font: 8pt verdana;" runat="server" />

</body>
</html>

Der Formularteil des Scripts ist bereits aus dem vorigen Listing bekannt, einzig und allein das Feld für die Namensgebung der Datei am Server fehlt - man braucht es nicht mehr. Was sind nun aber die Änderungen am Code für den Upload selbst? Im Grunde ist es nur dieser Part:

const int BUFFER_SIZE = 255;
int nBytesRead = 0;
Byte[] Buffer = new Byte[BUFFER_SIZE];
StringBuilder strUploadedContent = new StringBuilder("");

Stream theStream = uplTheFile.PostedFile.InputStream;
nBytesRead = theStream.Read(Buffer, 0, BUFFER_SIZE);

while (0 != nBytesRead)
{
  strUploadedContent.Append(
          Encoding.ASCII.GetString(Buffer,0,nBytesRead));
  nBytesRead = theStream.Read(Buffer,0,BUFFER_SIZE);
}

Zuerst definiere ich eine Konstante, und instanziere darauffolgend drei Variablen, die in der Bearbeitung der Streamdaten benötigt werden: eine Variable, die die Anzahl der gelesenen Bytes speichert, der Puffer für die gelesenen Daten, und der StringBuilder, der dazu verwendet wird, um die auf ASCII konvertierten eingelesenen Streamdaten zu speichern.

Und dann beginnt die Action - zuerst hole ich mir eine Referenz auf den Stream, der über das Object HttpPostedFile zur Verfügung gestellt wird (dieses wiederum über die Eigenschaft PostedFile des HtmlInputFile Objects). Dadurch erspare ich mir weitere Zugriffe auf Eigenschaften und fremde Objekte, die nur die Rechenzeit verlängern würden.

Dann lese ich die ersten Daten ein, und steige damit in die while Schleife ein. Dort wird der Puffer auf ASCII konvertiert, und die nächsten Daten eingelesen. Die while Schleife wird dann abgebrochen, wenn keine Daten mehr am Server angekommen sind.

Ist die while Schleife beendet, habe ich die Daten als String zur Weiterverarbeitung in der Hand - anstatt sie zurück an den Client zu schicken, könnte ich auch den String parsen - oder in eine Datenbank schreiben. Der Anwendungsfall bestimmt die Weiterverwendung.

Übrigens: wenn man die unmodifizierten Binärdaten verwenden möchte, dann sollte man die Konvertierung auf ASCII unterlassen, und je nach Bedarf den richtigen "Zwischenspeicher" verwenden - ein großes Bytearray, einen MemoryStream oder eigene Datenstrukturen.

Schlußbemerkung

In diesem Artikel habe ich Ihnen zwei Methoden des Dateiuploads vorgestellt: das Speichern der upgeloadeten Datei am Server mit Hilfe der SaveAs Methode, als auch das direkte Auslesen der Daten mit Hilfe des Stream Objekts. Die letztere Methode wird dann zum Einsatz kommen, wenn man direkt mit den Daten der Datei weiterarbeiten möchte, ohne vorher den Umweg über eine physikalische Datei am Server zu gehen.

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Beliebige Anzahl von Dateien uploaden
Dateien mit dem Browser auf Webserver laden
Dateiupload mit ASP und WSC
Dateiupload mit ASP.NET und VB.NET
Exception Handling in C#
Kontrollstatements in C#
On-the-fly Generierung von Graphiken
Schleifenbefehle in C#
Uploaden einer beliebigen Datei in eine Datenbank
Vergleich von DataGrid, DataList und Repeater-Control - was verwende ich wann?
Verwendung von Arrays in C#
Web-basiertes Dateimanagement mit dem ASP FileMan

Links zu anderen Sites

ASP.NET Download
Die aspDEdotnet Liste

Wenn Sie jetzt Fragen haben...

Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten.

Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist.

Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.

 

Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.