Uploading Files

A very useful file access feature under ASP.NET is its file upload capability. You can present a form containing a text box and browse button for users to navigate their local PC directories to locate a file for uploading. By clicking a button users can copy the local file to a server directory. This feature is illustrated by creating a file upload form for copying book pictures to the c:\eCommerce\BookPictures directory. The upload function is disabled, but you should get a good sense of how it works. The following form restricts uploads to JPG files no larger that 100 KB.

Picture Upload

Select file:

 
Figure 10-31. File uploading.

The <asp:FileUpload> Control

File uploading takes place through an <asp:FileUpload> control. This control produces a textbox along with a "Browse" button for navigating local computer directories to locate a file for uploading. The general format for this control is shown below.

<asp:FileUpload id="id" Runat="Server"/>
Figure 10-32. General format for <asp:FileUpload> control.

The control needs to be accompanied by a button to call a subprogram to copy the selected file to a server directory and to report on characteristics of the uploaded file. Code for the above control, its activation button, and its upload message Label is shown below.

<h3>Picture Upload</h3>

<b>Select file: </b>
<asp:FileUpload id="FileUp" Width="300px" Runat="Server"/>
<asp:Button Text="Upload" OnClick="Upload_File" Runat="Server"/><br/>
<br/>
<asp:Label id="Message" Text=" " ForeColor="#FF0000" Runat="Server"
  EnableViewState="False"/>
Listing 10-37. Code for file uploading.

File Upload Properties and Methods

An <asp:FileUpload> control has several properties and methods to manage file uploading. These are listed in Figure 10-33.

Properties:
  Control.HasFile
  Control.FileName
  Control.PostedFile.ContentLength

Methods:
  Control.SaveAs("path")
Figure 10-33. File upload properties and methods.

Whether or not a file has been selected and appears in the input box is given by the control's HasFile property. This property returns True or False for a script to determine whether to proceed with file uploading.

The FileName property gives the name of the file selected for uploading. This is a reference only to the file name, not to the entire file path showing in the input area.

The PostedFile property is a reference to the file chosen for uploading. This file object's ContentLength property returns the size of the file in bytes.

The control's SaveAs("path") method writes the uploaded file to a server directory given by the path string. The FileName property is appended to this path to copy the file to the designated directory.

File Upload Scripting

The following script references these properties and methods to upload a picture file to the "c:\eCommerce\BookPictures\" directory. This subprogram performs tests on missing file selections, non-JPG file types, and file sizes in addition to uploading a file.

Sub Upload_File (Src As Object, Args As EventArgs)

  If Not FileUp.HasFile Then
    '-- Missing file selection
    Message.Text = "Please choose a file to upload."
  ElseIf InStr(UCase(FileUp.FileName), ".JPG") = 0 Then
    '-- Selection of non-JPG file
    Message.Text = "You can upload only JPG files."
  ElseIf FileUp.PostedFile.ContentLength > 100000 Then
    '-- File too large
    Message.Text = "Uploaded file size must be less than 100 KB."
  Else
    '-- File upload
    FileUp.SaveAs(Server.MapPath("../BookPictures/") & FileUp.FileName)
    Message.Text = "<b>File Uploaded</b><br/>"
    Message.Text &= "File Name: " & FileUp.FileName & "<br/>"
    Message.Text &= "File Size: " & FileUp.PostedFile.ContentLength & _
                    " bytes<br/>"
  End If

End Sub
Listing 10-38. Script for file uploading.

First, a check is made that a file has been chosen for uploading by testing the FileUp.HasFile property. If the textbox is empty, then a message is written to the Message Label and the script ends.

A second check is made to ensure that only JPG files are uploaded. The FileUp.FileName property is checked to make sure that it contains the substring ".JPG". If not, then a message is written to the Message control and the script ends. The file name is converted to upper-case characters for the test to ensure that both ".JPG" and ".jpg" files are accepted.

A third check is made on the size of the upload file as given by its FileUp.PostedFile.ContentLength property. Files that are larger than 100,000 bytes in length are rejected.

The file is saved to a server directory by appending the FileUp.FileName property to a directory path in calling the SaveAs() method. If a file of the same name appears in the directory, it is overwritten.

Managing Picture Files

A useful sidebar to file uploading is giving users the ability to view the file that is uploaded. This feature is provided in the following example which displays all files in the c:\eCommerce\BookPictures directory along with a button to delete any of the picture files.

Contents of BookPictures Directory

BU111.jpg
BU222.jpg
BU333.jpg
DB111.jpg
DB222.jpg
DB333.jpg
DP111.jpg
DP222.jpg
GR111.jpg
GR222.jpg
GR333.jpg
GR444.jpg
GR555.jpg
OS111.jpg
OS222.jpg
OS333.jpg
WB111.jpg
WB222.jpg
WB333.jpg
WB444.jpg
Figure 10-34. Picture file display.

Pictures are displayed in an <asp:DataList> control whose code is shown below.

<asp:DataList id="PictureFiles" Runat="Server"
  RepeatColumns="4"
  RepeatDirection="Horizontal"
  CellPadding="3"
  GridLines="Both"
  OnItemCommand="Delete_File">

  <ItemTemplate>
    <asp:Image ImageUrl='<%# "../BookPictures/" & Container.DataItem %>'
      Width="45" ImageAlign="Left" Runat="Server"/>
    <asp:Label Text='<%# Container.DataItem %>' Runat="Server"/><br/>
    <asp:Button Text="Delete" Runat="Server"
      Font-Size="7pt"
      CommandName='<%# Container.DataItem %>'/>
  </ItemTemplate>

</asp:DataList>
Listing 10-39. Code for DataList display of picture files.

Binding Files to a Display Control

Files cannot be bound to a DataList or to other display controls. There is no data source control for file binding as there is for database binding. An intermediate step is needed, then, to import file names into a data structure that, in turn, can be bound to the control. A Visual Basic array is a common way to store file names that can serve as a binding source for a display control.

In the following script that accompanies the example DataList control, a list of file names is taken from the c:\eCommerce\BookPictures directory and assigned to an array. This array is then bound to the DataList as properties for the Image, Label, and Button controls to display and delete these files. This binding is coded in a separate Bind_Picture_Files subprogram since it takes place on two different occasions. File names are bound to the control when the page first loads; rebinding takes place after a file is deleted.

<%@ Import Namespace="System.IO" %>

<SCRIPT Runat="Server">

Sub Page_Load

  If Not Page.IsPostBack Then
    Bind_Picture_Files
  End If

End Sub

Sub Bind_Picture_Files

  Dim FileArray() As String 
  FileArray = Directory.GetFiles(Server.MapPath("../BookPictures"), "*.jpg")

  Dim i As Integer
  For i = 0 to UBound(FileArray)
    FileArray(i) = Replace(FileArray(i), Server.MapPath("../BookPictures/"), "")
  Next

  PictureFiles.DataSource = FileArray
  PictureFiles.DataBind()

End Sub

Sub Delete_File (Src As Object, Args As DataListCommandEventArgs)

  File.Delete(Server.MapPath("../BookPictures/") & Args.CommandName)
  Bind_Picture_Files

End Sub

</SCRIPT>
Listing 10-40. Script to bind picture files to DataList.

Accessing Directories and Files

In the above Bind_Picture_Files subprogram, an array named FileArray() is declared and becomes the target for the Directory.GetFiles() method. This method produces an array of paths to the files in the BookPictures directory, restricted to files with the ".jpg" extension.

Once an array of data values exists, it can be bound to a display control. In the current example, however, only the file names are needed, not the full paths appearing in FileArray(). Therefore, the file paths are converted to file names by iterating the array and replacing the path portion of the strings with a null character. This iteration produces an array of file names for all the .jpg files in the BookPictures directory.

Binding an Array to a Display Control

An array is bound to an output control by assigning it as the DataSource property of the control and calling the control's DataBind() method. Binding of array values takes a binding expression in the following format.

<%# Container.DataItem %>
Figure 10-35. Binding expression for array values.

The Container.DataItem expression is the array equivalent to the Eval() and Bind() expressions used in database binding. For each element in the array, a row is produced in the output control.

In the present example, the 30 elements in FileArray() produce 30 ItemTemplates in the DataList. FileArray() values (picture file names) are bound to the ImageUrl property of the Image controls, to the Text property of the Label controls, and to the CommandName property of the "Delete" Buttons. This ItemTemplate portion of the DataList is repeated in the following listing.

<ItemTemplate>
  <asp:Image ImageUrl='<%# "../BookPictures/" & Container.DataItem %>'
    Width="45" ImageAlign="Left" Runat="Server"/>
  <asp:Label Text='<%# Container.DataItem %>' Runat="Server"/><br/>
  <asp:Button Text="Delete" Font-Size="7pt" Runat="Server"
    CommandName='<%# Container.DataItem %>'/>
</ItemTemplate>
Listing 10-41. Code to bind picture files to a DataList.

Deleting Picture Files

A DataList, like other bound controls such as a GridView or DetailsView, recognizes Command events to which subprograms can be attached. Notice in the following partial listing that the DataList traps for this event with its OnItemCommand event handler which calls subprogram Delete_Picture when a Command event is triggered. This event takes place whenever a DataList button is clicked, in this case when the "Delete" Button associated with a picture is clicked.

Sub Delete_File (Src As Object, Args As DataListCommandEventArgs)

  File.Delete(Server.MapPath("../BookPictures/") & Args.CommandName)
  Bind_Picture_Files

End Sub

<asp:DataList id="PictureFiles" Runat="Server"
  OnItemCommand="Delete_File">
  ...
Listing 10-42. Code to raise a Command event to call a subprogram to delete a picture file.

The subprogram receives the button's CommandName through its DataListCommandEventArgs argument list. Since button CommandNames are the names of picture files, the subprogram receives the name of a file to delete through its Arg.CommandName argument. This argument is used in the Directory class' File.Delete() method, supplying the full path to the file to delete. Since the contents of the BookPictures directory change with a deletion, the Bind_Picture_Files subprogram is called to re-bind the directory listing to the DataList.