File Uploads met standaard ASP.NET In deze tutorial gaan we een aspx pagina maken (met codebehind), waarmee je een bestand kan uploaden naar de webserver. Noot: de hier beschreven code gaat niet in op het enumereren van de aanwezige bestanden in de upload folder zoals op bovenstaand screenshot. Dit screenshot komt van een ASP.NET applicatie die ik maakte voor eigen gebruik, gebaseerd op de technieken beschreven in deze tutorial.
1. De ASP.NET webapplicatie opmaken Start een nieuw C# ASP.NET Web Application project. Standaard zal er reeds 1 aspx pagina aanwezig zijn in het project, namelijk WebForm1.aspx. Op deze WebForm1 gaan we ons file upload form maken. Dubbelklik op WebForm1.aspx in het Solution Explorer venster van Visual Studio. Je zal automatisch naar het Design venster van de WebForm1.aspx pagina gebracht worden. Sleep een TextBox en een Button uit de Visual Studio Toolbox op je WebForm1 pagina. Noem de TextBox txtuploadfile. Vooraleer we naar de code voor deze file upload functionaliteit gaan, gaan we eerst wat aanpassingen doen in de HTML code van de WebForm1 pagina. Om bestanden te uploaden hebben we een input type=file nodig in plaats van de geplaatste TextBox. We gaan deze dus moeten aanpassen. Noot: De reden dat ik jullie een TextBox laat plaatsen, is omdat indien je opmaak toekent aan een TextBox, je deze opmaak dan makkelijker kan overnemen voor de input type=file box. Het is natuurlijk ook perfect mogelijk de input type=file box onmiddellijk via HTML toe te voegen. Noot: Ja kan ook een input type= file control in de toolbox vinden onder HTML controls. Maar wegen de eerder aangehaalde opmaak stel ik toch voor een TextBox te gebruiken, en deze nadien aan te passen. Ga naar de HTML weergave van de WebForm1.aspx pagina in Visual Studio.
De form van je pagina ziet er ongeveer als volgt uit: <form id="form1" method="post" runat="server"> <asp:textbox id="textbox1" style="z-index: 101; LEFT: 40px; POSITION: absolute; TOP: 40px" runat="server" Width="280px" Height="24px"></asp:TextBox> <asp:button id="button1" style="z-index: 102; LEFT: 40px; POSITION: absolute; TOP: 88px" runat="server" Width="192px" Height="40px" Text="Button"></asp:Button> </form> De Form encoding Het eerste dat we moeten wijzigen is de encoding van onze form. <form id="form1" method="post" runat="server" enctype= multipart/form-data > Dit is nodig omdat we niet slechts gewone form gegevens wensen door te sturen, maar een bestand. Onze input type=file opmaken Als tweede moeten we onze asp:textbox wijzigen. Zoals je kan zien is er reeds een style attribuut aanwezig met wat opmaak (dit is dus de reden dat we eerst een TextBox plaatsten). Er zijn enkel nog enkele attributen, zoals width en height, die we zelf gaan moeten toevoegen aan het style attribuut. Wijzig je TextBox als volgt : <input type="file" id="txtuploadfile" style="z-index:101; left:40px; width:280px; POSITION:absolute; height:24px; top:40px;" runat="server" /> Zorg ervoor dat je zeker runat= server niet vergeet, want deze inputbox moet serverside werken om het bestand te verschepen van de client naar de server. Vergeet ook de id niet voor deze servercontrol, want het is via die naam dat we het te uploaden bestand kunnen aanspreken.
2. De code voor de file upload Over naar de code. Je hebt een folder nodig waarin je de geuploadde bestanden kan opslaan. Ik gebruik een folder files, die een subfolder is van mijn ASP.NET applicatie. Noot: Zorg ervoor dat de ASPNET service de correcte permissies heeft. In deze tutorial ga ik niet in op het instellen van permissies voor ASP.NET webapplicaties. In mijn geval noemde ik mijn webapplicatie Argon. Visual Studio maakt automatisch een Webshared folder aan in je IIS webserver. Onder die folder maakte ik dus een subfolder, files genaamd. Ga naar Design View voor WebForm1.aspx en dubbelklik op de knop die je erop plaatste. Je wordt automatisch naar de codebehind voor je aspx pagina gebracht, Visual Studio genereert zelf een click event voor de knop, en je wordt gebracht naar de methode die uitgevoerd moet worden bij dat click event. Eerst moeten we specifiëren naar welke folder we wensen te uploaden. string strbaselocation = Server.MapPath( "./files" ); We maken een kleine methode die de bestandsnaam haalt uit het filepath dat door de client die wenst te uploaden wordt opgegeven (de code spreekt voor zich) : private string GetFileName(string filefullpath) string[] tmp = filefullpath.split('\\'); return tmp[ tmp.length-1 ];
Nu kunnen we het volledige doelpath voor het bestand op de server opmaken: string filename = GetFileName( txtuploadfile.value ); string filetarget = strbaselocation + "\\" + filename; Geloof het of niet, wat we tot nu toe gedaan hebben is het grootste werk! Om het bestand daadwerkelijk te uploaden naar de server is slechts 1 regel code nodig: txtuploadfile.postedfile.saveas(filetarget); Voila. Als je de tutorial correct volgde zou de file upload nu zonder meer moeten werken. Er zijn echter nog enkele randnota s te vermelden - Standaard is de maximum uploadbare bestandsgrootte 4000 kilobytes (ca. 4 mb). Dit kan gewijzigd worden via het web.config bestand van je project, door middel van de httpruntime node in dat xml document. Hier ga ik echter niet op in (als je deze functionaliteit echt nodig hebt, start dan je zoekopdracht bij httpruntime in de MSDN documentatie). Grotere bestanden uploaden gebeurt beter via ftp, of één of ander upload component. Als je toch een groter bestand probeert up te loaden met bovenstaande code krijg je een The page cannot be displayed pagina te zien, dit vanwege de fout tegen de httpruntime instellingen. Zoals hierboven reeds aangehaald, krijg je bij het uploaden van te grote bestanden een The page cannot be displayed te zien. Het lijkt echter niet mogelijk de bestandsgrootte op te vragen voordat deze geupload wordt, waardoor je enkel kan berusten op een melding bij de inputbox max 4000 kilobyte (zie screenshot helemaal bovenaan) aan je clients. In bovenstaande code deden we niks van error handling. Verder in deze tutorial vind je enkele alternatieve codevoorbeelden, alt#1 stelt de hoger besproken code voor met uitgebreidere foutcontrole. alt#2 geeft alternatieve code weer, waarbij we het bestand opslaan aan de hand van de InputStream van het PostedFile object. We lezen het bestand byte per byte, en schrijven het byte per byte weg via een filestream.
ALT #1 private void btnupload_click(object sender, System.EventArgs e) string strbaselocation = Server.MapPath( "./files" ); if( txtuploadfile.value == string.empty ) Console.WriteLine("Geen bestand geselecteerd."); return; string filename = GetFileName( txtuploadfile.value ); string filetarget = strbaselocation + "\\" + filename; if( File.Exists( filetarget ) ) Console.WriteLine("Bestand bestaat reeds"); return; if ( txtuploadfile.postedfile!= null ) try txtuploadfile.postedfile.saveas(filetarget); catch(exception ex) Console.WriteLine( "Fout bij het uploaden + ex.message);
ALT #2 private void btnupload_click(object sender, System.EventArgs e) string strbaselocation = Server.MapPath( "./files" ); if( txtuploadfile.value == string.empty ) Console.WriteLine("Geen bestand geselecteerd"); return; string filename = GetFileName( txtuploadfile.value ); string filetarget = strbaselocation + "\\" + filename; if( File.Exists( filetarget ) ) Console.WriteLine("Bestand bestaat reeds"); return; if ( txtuploadfile.postedfile!= null ) try //incoming external file stream Stream thestream = txtuploadfile.postedfile.inputstream; //local file stream FileStream fs = new FileStream(fileTarget, FileMode.CreateNew, FileAccess.Write); int r = 0; while((r=thestream.readbyte())!= -1 ) fs.writebyte((byte)r); thestream.close(); fs.close(); catch(exception ex) Console.WriteLine("Fout bij het uploaden.<br>" + ex.message);
Veel plezier. Kris.