By Ziran Sun
With the inclusion of the FileUpload control in ASP.NET 2.0, Microsoft has finally
given us a WebControl to handle file uploading. In this article we’ll examine the
new FileUpload control and show just how easy it is to build an ASP.NET Web Form
that accepts user uploads.
A Little History
When ASP was first released, it was generally accepted that if you wanted the ability to upload a file,
you needed to either write or buy a component to do it for you. Upload components quickly became one
of the most popular components you could buy and it seemed that every 3rd party component
vendor offered one. So uploading was now possible, you just had to choose a component. The problem was that
while they all allowed you to upload files, the performance varied from one to the next, the different
components all had different bells and whistles, and they all worked just a little bit differently.
To make matters worse, if you were a freelance developer of a small guy dealing with shared hosting, you
probably didn’t even get to choose which upload component to use.
In not sure if it was the release of ASP 3.0 or simply the newer versions of VBScript that enabled it,
but eventually someone discovered that it was now possible to process an upload completely in script.
Soon there were a bunch of plain script "upload libraries" floating around in addition to the
components. While the plain script option was nice and allowed to you deal with uploads without the
need to install a component, even the best scripts were slower then the average component and the worst
were many times slower.
With the release of ASP.NET 1.x, it seemed that all our problems had been solved. The .NET Framework
was supposed to make everything easy and for the most part it did. Handling uploads was much easier,
but you still had to remember to set the form "enctype" property to "multipart/form-data"
and there was no WebControl to handle the UI for you. Sure there’s the "HtmlInputFile" HtmlControl, but
honestly, how many developers were out there using HtmlControls? Who wants to deal with all the work
involved building a "HtmlTable" by hand when you can just drag and drop a "DataGrid"
onto your form, DataBind to your data, and have .NET do all the work for you?
Don’t get me wrong, ASP.NET 1.x made dealing with uploads much simpler then it had ever been in the past,
but there were still a few loose ends.
Microsoft clarified things a little by publishing a KnowledgeBase article on the topic:
How to upload a file to a Web server in ASP.NET by using Visual Basic .NET,
but it wouldn’t be until the release of ASP.NET 2.0 and the inclusion of the new FileUpload control that
those loose ends would finally be tied up.
The ASP.NET 2.0 FileUpload Control
The new ASP.NET 2.0 FileUpload control (
<asp:FileUpload>) finally adds the last piece to the
upload puzzle. It takes care of those last little annoying things and finally makes it easy to design an ASP.NET
page that handles uploading by simply dragging the control onto the page. Speaking of which, you’ll find the
control on the "Standard" tab in your Visual Studio 2005 Toolbox.
Dragging and dropping it onto a WebForm gives you the following UI:
and the code behind that should look something like this:
<asp:FileUpload ID="FileUpload1" runat="server" />
Oh and in terms of setting that pesky "enctype" property on the form… there’s
no need to worry about it. ASP.NET handles it for you. The property isn’t there at design time,
but when the page is run, the server sees that the upload control is there and adds it for you.
If you do a "View Source" from your browser, you’ll see it sitting there plain as day.
Handling the Uploaded File
While the FileUpload control handles the UI for you, you’ll still need to write the code to tell
the server what to do with the file being uploaded. The code is similar to any upload code you may
have written in ASP.NET 1.x, but instead of accessing the uploaded file via an HtmlInputFile control
you’ll be accessing it via the FileUpload control instead. Here’s a sample upload page that’s about
as simple as it gets:
<%@ Page Language="VB" %>
Protected Sub btnFileUpload_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If myFileUpload.HasFile Then
myFileUpload.SaveAs(Server.MapPath("uploads/" & myFileUpload.FileName))
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<title>ASP.NET 2.0 FileUpload Control Sample</title>
<form id="myForm" runat="server">
<asp:FileUpload ID="myFileUpload" runat="server" />
<asp:Button ID="btnFileUpload" runat="server"
There are three main things to notice in the code listing above. First, in order to determine if a file has actually
been uploaded, we check the "HasFile" property of our FileUpload control. We then use the
"SaveAs" method to save the file to disk. Finally, in order to determine what to name the
file, we get the name of the file that was uploaded via the "FileName" property. That’s really all
there is to it.
The above listing is obviously a very bare bones version of an upload script, but it just goes to show how little
code we actually have to write in order to get a great deal of functionality. The version pictured below is available
in the zip file and shows you a little more detail, adds some error handling, and accesses a few properties of the
"PostedFile" object, but the heart of the script is the same.
The first security issue that you’ll probably face is that when you attempt to upload a file,
the script will probably display an access denied error. That’s because by default, anonymous
users usually don’t have permission to write to the server’s hard drive. If you want users to
be able to upload files, you’ll need to relax that restriction somewhat. When you do so,
you need to be very careful and think about exactly what you’re enabling users to do.
Whenever you allow users to upload files, you’re exposing yourself to the possibility that
a user may attempt to upload files containing malicious content. This can include viruses,
executable files, scripts, spyware, etc. As such, there are a few things you should always
check before deploying any application that includes the ability to upload files.
First of all, it’s best if you don’t let users upload files to folders that are accessible
via the web. For example, if your web site is published to "C:\inetpub\wwwroot\"
then ideally anything underneath that should be off limits. That includes any folders that
may be outside that physical folder but are mapped as virtual directories via IIS.
If you must allow users to upload files to a folder that can be accessed via the web then
you need to be absolutely sure that you set the NTFS settings on that folder to not allow
execution. Otherwise you could find yourself in a situation where a user can upload a
file that does whatever they want and then they can request the file via a browser and
cause it to run.
Another way to attempt to stop users from uploading harmful files is to examine each file’s
characteristics (file extension and ContentType) before saving the file to the hard drive.
The main problem with this approach is that there are lots of types of files that can contain
malicious content. Aside from standard .exe/.com programs and .asp/.aspx scripts, you’ve
also got to worry about .vbs, .js, .pif, .bat, .cmd, .wsh, .reg, and who knows what other
types of files. A better approach then trying to not allow certain file types is to only
allow the types of files that you’re expecting. For example, if you’re letting users upload
images, it’s much better to only allow users to save .gif, .jpg, .jpeg, and .png files then
to try and rule out all the malicious file types.
If you’d like a copy of the sample above, you can download a zip file containing the source code
below: ASP.NET 2.0 FileUpload Control Sample (1 KB).
With the inclusion of the FileUpload Control in ASP.NET 2.0, Microsoft has finally
tied up all the loose ends that were left when it comes to managing file uploads
from ASP.NET. Not only are we now able to simply drag and drop the new control
onto a page, but it also handles setting the form’s enctype for us and provides a rich
object model that lets us handle uploads more easily then ever before.