Thursday, November 19, 2009

Multiple File Uploads in ASP.NET with Add/Remove and Up/Down functionalities

HTML or ASP.NET does not allows you to select more then one file in a single file upload input field. To work around this shortcoming you will either have to add dynamic file upload fields by using JavaScript or use a single file upload field to upload the files one by one.

I have devised a nifty technique by using the ASP.NET ListBox control to keep track of the added files and manage them. You can add/remove or change the upload order of the files before uploading them all to your server/database. Sometimes the order of your file upload is also very important and it becomes more easier with this technique where you can arrange them by using the Up/Down controls.

Multiple File Uploads in ASP.NET

The code for the .aspx file is pretty straight forward with a FileUpload control, a ListBox control and buttons to handle all the functionalities. You can even implement this code as an ASP.NET User Control for your project.

Here is the File Upload code for .aspx file:
<table>
<tr>
    <td colspan="2">
    <font color="red"><asp:Label ID="Message" runat="server" Text=""></asp:Label></font>
    </td>
</tr>
<tr>
    <td colspan="2">
    <asp:FileUpload runat="server" id="FileUploader" Width="300"></asp:FileUpload>
    </td>
</tr>
<tr>
    <td>
    <asp:ListBox ID="FileListBox" runat="server" Width="300" Rows="5" SelectionMode="Single" BackColor="AliceBlue">
    </asp:ListBox>
    </td>
    <td>
    <asp:Button ID="Up" runat="server" Text="&uarr;" Font-Bold="true" Font-Size="Large" /><br />
    <asp:Button ID="Down" runat="server" Text="&darr;" Font-Bold="true" Font-Size="Large" /><br />
    </td>
</tr>
<tr>
    <td colspan="2">
    <asp:Button ID="Add" runat="server" Text="Add" />
    <asp:Button ID="Remove" runat="server" Text="Remove" />
    <asp:Button ID="Upload" runat="server" Text="Upload" />
    </td>
</tr>
</table>
<br /><br />
<asp:Literal ID="FileList" runat="server"></asp:Literal>

The backend code in VB is also pretty easy to understand with subroutines to handle the button click events. To keep track of all the files added to the list we use a Listbox control and to store the HttpInputFile objects we use a global ArrayList named Files. For saving the files I have used an example of storing the files in a Database using stored procedure, but you can always save the file to your server itself by using the HIF.PostedFile.SaveAs method. Detailed description for the functionality of each button click event subroutine is given below:

  • Add_Click: Fires when the user browses a file and click on the Add button. Error checking is done to ensure if the FileUpload control has input file, if the file size is not zero and does the file already exists in the list or not. After error checking is passed, the file name is added to to List Box and also to the global ArrayList which holds the object to the HttpInputFile class.
  • Remove_Click: This subroutine simply removes the file name at selected index from the List Box and from the Files Array.
  • Up_Click: The position of the selected item is switched with the item on top of it in the List Box and the Array List.
  • Down_Click: The position of the selected item is switched with the item below it in the List Box and the Array List.
  • Upload_Click: All the files in the Files Array are uploaded to the database using stored procedure.

Here is the VB file code for the File Uploader:

Imports System.Data.SqlClient

Partial Public Class _Default
    Inherits System.Web.UI.Page

    Public Shared Files As ArrayList = New ArrayList()
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    End Sub

    Protected Sub Add_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Add.Click
        Try
            Message.Text = ""
            If FileUploader.HasFile Then 'Check if file exists...
                If FileUploader.PostedFile.ContentLength > 0 Then 'Check file size
                    If FileListBox.Items.Contains(New ListItem(System.IO.Path.GetFileName(FileUploader.PostedFile.FileName))) Then
                        Message.Text = "File already in the list!"
                    Else
                        Files.Add(FileUploader)
                        FileListBox.Items.Add(System.IO.Path.GetFileName(FileUploader.PostedFile.FileName))
                        Message.Text = "Add another file or click Upload to save them all..."
                    End If
                Else
                    Message.Text = "File size cannot be 0!"
                End If
            Else
                Message.Text = "Please select a file to add!"
            End If
        Catch ex As Exception
            ' Handle Error
        End Try
    End Sub

    Protected Sub Remove_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Remove.Click
        If FileListBox.Items.Count > 0 Then
            If FileListBox.SelectedIndex < 0 Then
                Message.Text = "Please select a file to remove!"
            Else
                Files.RemoveAt(FileListBox.SelectedIndex)
                FileListBox.Items.Remove(FileListBox.SelectedItem.Text)
                Message.Text = "File removed..."
            End If
        End If
    End Sub

    Protected Sub Up_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Up.Click
        If FileListBox.Items.Count > 1 AndAlso FileListBox.SelectedIndex > 0 Then
            Dim index As Integer = FileListBox.SelectedIndex
            Dim toMove As String = FileListBox.SelectedValue
            'Move up filename in ListBox
            FileListBox.Items.Insert(index - 1, toMove)
            FileListBox.Items.RemoveAt(index + 1)
            FileListBox.Items.Item(index - 1).Selected = True
            'Move up file in Files ArrayList
            Dim TempFileHandle As FileUpload = Files(index - 1)
            Files(index - 1) = Files(index)
            Files(index) = TempFileHandle
        End If
    End Sub

    Protected Sub Down_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Down.Click
        If FileListBox.Items.Count > 1 AndAlso FileListBox.SelectedIndex < FileListBox.Items.Count - 1 Then
            Dim index As Integer = FileListBox.SelectedIndex + 1
            Dim toMove As String = FileListBox.Items.Item(index).Text
            'Move down filename in ListBox
            FileListBox.Items.Insert(index - 1, toMove)
            FileListBox.Items.RemoveAt(index + 1)
            FileListBox.Items.Item(index).Selected = True
            'Move down file in Files ArrayList
            Dim TempFileHandle As FileUpload = Files(index - 1)
            Files(index - 1) = Files(index)
            Files(index) = TempFileHandle
        End If
    End Sub

    Protected Sub Upload_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Upload.Click
        Dim conn As SqlConnection = New SqlConnection("")
        conn.Open()
        For Each HIF As FileUpload In Files
            FileList.Text += "Uploading file: " & HIF.PostedFile.FileName + "<br />" + vbCrLf
            Dim fileBytes(HIF.PostedFile.InputStream.Length) As Byte
            HIF.PostedFile.InputStream.Read(fileBytes, 0, fileBytes.Length)
            Dim Command As New SqlCommand
            With Command
                .Connection = conn
                .CommandType = CommandType.StoredProcedure
                .CommandText = "upload_files"
                .Parameters.AddWithValue("@id", System.Guid.NewGuid.ToString())
                .Parameters.AddWithValue("@name", System.IO.Path.GetFileName(HIF.PostedFile.FileName))
                .Parameters.AddWithValue("@size", HIF.PostedFile.ContentLength)
                .Parameters.AddWithValue("@type", HIF.PostedFile.ContentType)
                .Parameters.AddWithValue("@file", fileBytes)
                .Parameters.AddWithValue("@dateadded", DateTime.Now())
            End With
            Command.ExecuteNonQuery()
        Next
        conn.Close()
        Message.Text = ""
        'Clear Files ArrayList
        Files.Clear()
        'Clear File List Box
        FileListBox.Items.Clear()
    End Sub
End Class

This implementation contains very minimal amount of code to attain the desired functionalities, you can always add more error checking or styles to suit your website design.

2 comments:

  1. As you hav declared arraylist as static the given solution not working when more then one user are trying is there any alternative for static arraylist

    ReplyDelete
  2. TechnoSoftwar having several years experience working with global customers, connecting our professionals to their business needs, as their IT Development & Support Partner. TechnoSoftwar having a team of dedicated and experienced softwares developers that works for your all business needs. TechnoSoftwar deals in web design and development, Customized ERPs, CRMs, Web & Mobile Applications, eCommerce platforms etc.

    ReplyDelete

Thanks a lot for your valuable comments :)