ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


ASP.NET File Uploading

by Budi Kurniawan
04/01/2002

Use ClickOnce to Deploy Windows Applications

File upload and download are much simpler tasks in ASP.NET than in classic ASP, thanks to the extensive .NET Framework class library. File upload in ASP.NET is as easy as retrieving an HTML form value. In classic ASP, it's a somewhat involved process, in which you have to extract the content of the uploaded file from raw HTTP request data. In the end, many ASP programmers resort to a third-party component for file upload.

File download is even easier in ASP.NET with the new WriteFile method in the Request object. Sending a file to the browser can be achieved using a single line of code. In classic ASP, you have to open the file yourself and send a number of bytes at a time. With file download, however, the same problem remains as in classic ASP and other Web technologies. Many Web programmers still wonder how they can force the browser to display the Download dialog. Sending the file with the WriteFile method will not necessarily display the dialog. The default behavior for browsers is that if the file's MIME type is recognized, the browser will either try to display the content or it will fire up an application associated with that MIME type. This "smart" behavior is often not the desired behavior. In this article, I will show you how to force the browser to always show the Download dialog, so the user can save the file to disk.

After some theory, this article will present a file upload and download utility you can use to manage files on your server. You can download all of the files for this article, including the image files, here.

File Download

To force the browser to display the Download dialog, you need to set the Response object's ContentType property to application/octet-stream and add an HTTP Request header called Content-Disposition with the following value: attachment; filename="filename" where filename is the default filename that will be displayed in the Download dialog at the browser. Therefore, to send a file to the browser, the first thing to do is to write the following code:


Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", _
  "attachment; filename=""" & filename & """")

Afterwards, you can send the file to the browser using the Response object's WriteFile method. You must not send anything before and after sending the file content. It is usually a good idea to clear the buffer prior to sending the file. The code in Listing 1 displays all the files in the C:\temp directory. The code in Listing 2 does the actual sending of the file to the browser.

Listing 1. Displaying the list of files


<%@ Import Namespace="System.IO"%>
<html>
<head>
<title>File Download</title>
<script language="VB" runat="server">


Sub Page_Load(sender As Object, e As EventArgs)
 
  Dim root As String = "C:\temp\"
 
  Dim files() As String = Directory.GetFiles(root)
  Dim sb As New StringBuilder(2048)
  Dim f As String
  For Each f In files
    Dim filename As String = Path.GetFileName(f)
    sb.Append("<br><a href=FileDownload.aspx?file=")
    sb.Append(root).Append(Server.UrlEncode(filename))
    sb.Append(">").Append(filename).Append("</a>")
  Next
  fileList.Text = sb.ToString()

End Sub

</script>
</head>
<body>
<form runat="server">
<asp:Label id="fileList" runat="server"/>
</form>
</body>
</html>

The code in Listing 1 only has one event handler: Page_Load. It first obtains all the file names in the specified directory (C:\temp) and puts them in an array of strings called files.


  Dim files() As String = Directory.GetFiles(root)

It then constructs a StringBuilder object as the output buffer.


  Dim sb As New StringBuilder(2048)
  Dim f As String

Next, it iterates all of the files in the array and constructs a hyperlink of the following format for each file in the directory.


<a href="FileDownload.aspx?file=path">filename</a>

where path is the full physical path of the file on the server.


  For Each f In files
    Dim filename As String = Path.GetFileName(f)
    sb.Append("<br><a href=FileDownload.aspx?file=")
    sb.Append(root).Append(Server.UrlEncode(filename))
    sb.Append(">").Append(filename).Append("</a>")
  Next
  fileList.Text = sb.ToString()

An important point is the use of the System.Web.HttpServerUtility classes to encode the file path so that it will be safely transferred in the URL. To send the file itself, you need FileDownload.aspx, shown in Listing 2.

Listing 2. FileDownload.aspx


<%@ Import Namespace="System.IO"%>
<script language="VB" runat="server">
Sub Page_Load(sender As Object, e As EventArgs)
 
  Dim root As String = "C:\temp\"
  Dim filepath As String = Request.Params("file")
  If Not filepath Is Nothing Then
    If File.Exists(filepath) And filepath.StartsWith(root) Then
      Dim filename As String = Path.GetFileName(filepath)
      Response.Clear()
      Response.ContentType = "application/octet-stream"
      Response.AddHeader("Content-Disposition", _
        "attachment; filename=""" & filename & """")
      Response.Flush()
      Response.WriteFile(filepath)
    End If
  End If

End Sub
</script>

File Upload

Related Reading

.NET Framework Essentials
By Thuan L. Thai, Hoang Lam

To perform file upload in ASP.NET, you need to know two classes: the System.Web.UI.HtmlControls.HtmlInputFile class and the System.Web.HttpPostedFile. The first class represents an HTML control that the user uses to select a file on the client side and upload it. The latter represents the uploaded file itself, and an instance of this class is obtained from the HtmlInputFile control. The next two subsections discuss each class in detail.

The HtmlInputFile Class

The System.Web.UI.HtmlControls.HtmlInputFile class is very simple and easy to use. It defines the following four properties:

To use the HtmlInputFile control, the containing form must have the enctype="multipart/form-data" defined. Here is an example of how to use the HtmlInputFile control in a Web form.


<form enctype="multipart/form-data" runat="server">
  Select File to Upload: 
  <input id="uploadedFile" type="file" runat="server">
  <input type=button id="upload" 
    value="Upload" 
    OnServerClick="Upload_Click" 
    runat="server">
</form>

The HttpPostedFile Class

This class represents an uploaded file. It has one method, SaveAs, that saves the uploaded file in the specified location on the server. In addition, it has the following four properties:

Uploading A File

The code in Listing 3 demonstrates a Web form that is enabled to upload a file. The user interface contains the following controls:

Listing 3. Uploading a file


<%@ Import namespace="System.IO"%>
<html>
<head>
<title>Uploading a File</title> 
<script language="VB" runat="server">

Dim savePath As String = "C:\temp\"
Sub Upload_Click(source As Object, e As EventArgs)

  If Not (uploadedFile.PostedFile Is Nothing) Then
    Try
      Dim postedFile = uploadedFile.PostedFile
      Dim filename As String = Path.GetFileName(postedFile.FileName)
      Dim contentType As String = postedFile.ContentType
      Dim contentLength As Integer = postedFile.ContentLength

      postedFile.SaveAs(savePath & filename)
      message.Text = postedFile.Filename & " uploaded" & _
        "<br>content type: " & contentType & _
        "<br>content length: " & contentLength.ToString()
    Catch exc As Exception
      message.Text = "Failed uploading file"
    End Try
  End If
End Sub 
</script>
 
</head>
<body>
 
<form enctype="multipart/form-data" runat="server">
  Select File to Upload: 
  <input id="uploadedFile" type="file" runat="server">
  <p>
  <input type=button id="upload" 
    value="Upload" 
    OnServerClick="Upload_Click" 
    runat="server">
  <p>
  <asp:Label id="message" runat="server"/>
</form>
 
</body>
</html>

The code in the Web form in Listing 3 has one event handler, Upload_Click, which is triggered when the user clicks the "Upload" button. The Upload_Click event handler first makes sure that the PostedFile property of the HtmlInputFile is not Nothing and obtains the filename, content type, and the content length.


      Dim postedFile = uploadedFile.PostedFile
      Dim filename As String = Path.GetFileName(postedFile.FileName)
      Dim contentType As String = postedFile.ContentType
      Dim contentLength As Integer = postedFile.ContentLength

The file is then saved in the specified save path and the filename, content type, and content length of the file are displayed in the message label control.


      postedFile.SaveAs(savePath & filename)
      message.Text = postedFile.Filename & " uploaded" & _
        "<br>content type: " & contentType & _
        "<br>content length: " & contentLength.ToString()

ASP.NET File Management

Based on the theory presented in the first two sections of this article, here is a useful application that you can use to manage files on a Web server. This application lets users navigate to the specified root folder and any subfolders under it, and upload or download files from/to those folders. (See Figure 1)


Figure 1. ASP.NET file management

To run the application, you need two pages: the Web form given in Listing 4, and the file download code given in Listing 2. You also need four image files that should be placed in the images subdirectory under the application directory:

Listing 4. ASP.NET File Management


<%@ Import Namespace="System.IO"%>
<html>
<head>
<title>File Management</title>
<script language="VB" runat="server">

Dim currentDir As String 
Dim directorySeparatorChar As Char = Path.DirectorySeparatorChar


Sub Page_Load(sender As Object, e As EventArgs)

  Dim root As String = "C:\temp"
  Dim thisPage As String = Request.Path

  currentDir = Request.Params("dir")
  If currentDir Is Nothing Then
    currentDir = root
  End If
  If Not currentDir.StartsWith(root) Then
    currentDir = root
  End If

  Dim sb As New StringBuilder(4096)

  If Not currentDir.Equals(Root) Then
    ' not at the root
    Dim currentDirParent As String
    Dim lastIndex As Integer = _
      currentDir.LastIndexOf(directorySeparatorChar)
    If lastIndex <> -1 Then
      currentDirParent = currentDir.Substring(0, lastIndex)
    Else
      currentDirParent = currentDir
    End If
    sb.Append("<a href=").Append(thisPage)
    sb.Append("?dir=").Append(Server.UrlEncode(currentDirParent))
    sb.Append("><img width=30 border=0 src=images/Up.gif></a><br>") 
  End If

  DoUpload()

  sb.Append("<br><img border=0 src=images/OpenFolder.gif> ")
  sb.Append("<font face=verdana>")
  sb.Append(currentDir)
  sb.Append("</font>")
  sb.Append("<br>")

  sb.Append("<table>")
  sb.Append("<tr bgcolor=#D8D8D8>")
  sb.Append("<td width=200><font face=verdana size=3>Name</font></td>")
  sb.Append("<td><font face=verdana size=3>Type</font></td>")
  sb.Append("<td><font face=verdana size=3>Size</font></td>")
  sb.Append("<td><font face=verdana size=3>Modified</font></td>")
  sb.Append("</tr>")


  Dim dirs() As String
  Try 
    dirs = Directory.GetDirectories(currentDir)

    Dim d As String
    For Each d In dirs
      Dim dirName As String = Path.GetFileName(d)
      sb.Append("<tr>")
      sb.Append("<td><img src=images/Folder.gif> ")
      sb.Append("<a href=").Append(thisPage)
      sb.Append("?dir=").Append(Server.UrlEncode(currentDir))
      sb.Append(directorySeparatorChar)
      sb.Append(Server.UrlEncode(dirName))
      sb.Append(">").Append(dirName).Append("</a>")
      sb.Append("</td>")
      sb.Append("<td><font face=verdana size=2>folder</font></td>")
      sb.Append("<td> </td>")
      sb.Append("<td><font face=verdana size=2>")
      sb.Append(Directory.GetLastWriteTime(currentDir & _ 
        directorySeparatorChar.ToString() & dirName).ToString())
      sb.Append("</font></td>")
      sb.Append("</tr>")


    Next

  Catch ex As Exception
  End Try
    

  Try
    Dim dirInfo As New DirectoryInfo(currentDir)
    Dim files() As FileInfo 
    files = dirInfo.GetFiles()

    Dim f As FileInfo
    For Each f In files
      Dim filename As String = f.Name
      sb.Append("<tr>")
      sb.Append("<td><img src=images/File.gif> ")
      sb.Append("<a href=FileDownload.aspx?file=")
      sb.Append(Server.UrlEncode(currentDir))
      sb.Append(directorySeparatorChar)
      sb.Append(Server.UrlEncode(filename))
      sb.Append(">").Append(filename).Append("</a>")
      sb.Append("</td>")
      sb.Append("<td><font face=verdana size=2>file</font></td>")
      sb.Append("<td><font face=verdana size=2>")
      sb.Append(f.Length.ToString())
      sb.Append("</font></td>")
      sb.Append("<td><font face=verdana size=2>")
      sb.Append(File.GetLastWriteTime(currentDir & _
        directorySeparatorChar.ToString() & f.Name).ToString())
      sb.Append("</font></td>")
      sb.Append("</tr>")
    Next
  Catch ex As Exception
  End Try

  sb.Append("</table>")
  dirContent.Text = sb.ToString()
End Sub


Sub DoUpload()
            
  If Not (uploadedFile.PostedFile Is Nothing) Then
    Try
      Dim postedFile = uploadedFile.PostedFile
      Dim filename As String = Path.GetFileName(postedFile.FileName)
      Dim contentType As String = postedFile.ContentType
      Dim contentLength As Integer = postedFile.ContentLength
      postedFile.SaveAs(currentDir & _
        directorySeparatorChar.ToString() & filename)
    Catch ex As Exception
      message.Text = "Failed uploading file"
    End Try
  End If
End Sub 


</script>
</head>
<body>
<form runat="server" enctype="multipart/form-data" >
<asp:Label id="dirContent" runat="server"/>
<asp:Label id="message" runat="server"/>
<p>
<hr>

<%-- File Upload --%>
<font face=verdana>Select File to Upload:</font> 
<input id="uploadedFile" type="file" runat="server">
<input type=button id="upload" 
  value="Upload" 
  OnServerClick="Page_Load" 
  runat="server">
<p>

</form>
</body>
</html>


Summary

File upload is much simpler in ASP.NET than in classic ASP. The first section of this article explained how to write code to upload a file, and the second section discussed programmable file download. The knowledge that you gain from the first two sections is then used in the ASP.NET file management utility offered in Listing 4 of this article.

Budi Kurniawan is a senior J2EE architect and author.


Return to the .NET DevCenter.

Copyright © 2009 O'Reilly Media, Inc.