Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Upload multiple files Hotmail style

0.00/5 (No votes)
28 Nov 2002 1  
Upload multiple files using one HttpInputControl

Sample Image

Introduction

I will briefly demonstrate how to upload multiple files using one HttpInputFile control - Hotmail style! Many developers have been asking how to upload multiple files at once. The <Input type=file/> allows a user to select only one file at a time thereby forcing a developer to use multiple <Input type=file/> on a page.

Background

This article is a repost of an article that I posted here about a week ago. There was a bug in the first article so I took it down after explaining the bug. If you missed the explanation here is a summary. The HttpInputControl control does not allow for the PostedFile value to be set at runtime. If that were the case then anyone could set a <Input type=file/> value with the name of a file that is on the client and download it. So this is by design that the value can not be set. I attempted to store the values of the selected files in a listbox and then pass those values to the HttpInputControl. In my rush to post I did not notice that empty files were being saved to the web server. So here is my second and I hope final attempt at demonstrating how to upload multiple files to a web server while using only one HttpInputControl control.

Using the code

Using this code could not get any simpler. It's almost to easy thanks to .NET! First there is my style sheet, StyleSheet.css. I am fond of the colored flat buttons so I created a style called 'bluebutton'. Next is the .aspx page, attachme.aspx followed by the code-behind attachme.aspx.cs.

My style sheet code for StyleSheet.css:

.bluebutton
{
 background-color:LightSteelBlue;
 border-style:solid;
 border-width: 1px;
 border-color: LightSkyBlue;
}

Now here is the code for attachme.aspx.

<%@ Page language="c#" Codebehind="attachme.aspx.cs" AutoEventWireup="false" 
     Inherits="webchange.attachme" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
     <HEAD>
     <title>attachme</title>
     <meta content="Microsoft Visual Studio 7.0" name="GENERATOR">
     <meta content="C#" name="CODE_LANGUAGE">
     <meta content="JavaScript" name="vs_defaultClientScript">
     <meta content="http://schemas.microsoft.com/intellisense/ie5" 
              name="vs_targetSchema">
     <LINK href="StyleSheet.css" rel="stylesheet">
     </HEAD>
    <body MS_POSITIONING="GridLayout">
        <form id="attachme" method="post" encType="multipart/form-data" runat="server">
            <INPUT class="bluebutton" id="FindFile" style="Z-INDEX: 101; LEFT: 36px; 
                      WIDTH: 274px; POSITION: absolute; TOP: 123px; HEIGHT: 22px" 
                      type="file" size="26" runat="server" NAME="FindFile">
            <asp:listbox id="ListBox1" style="Z-INDEX: 102; LEFT: 36px; 
                      POSITION: absolute; TOP: 149px" runat="server" CssClass="txtbox" 
                      Height="100px" Width="274px" Font-Size="XX-Small"></asp:listbox>
            <asp:button id="AddFile" style="Z-INDEX: 103; LEFT: 34px; POSITION: absolute; 
                      TOP: 254px" runat="server" CssClass="bluebutton" Height="23px" 
                      Width="72px" Text="Add"></asp:button>
            <asp:button id="RemvFile" style="Z-INDEX: 104; LEFT: 119px; 
                      POSITION: absolute; TOP: 255px" runat="server" 
                      CssClass="bluebutton"
                      Height="23px" Width="72px" Text="Remove"></asp:button>
            <INPUT class="bluebutton" id="Upload" style="Z-INDEX: 105; LEFT: 236px;
                      WIDTH: 71px; POSITION: absolute; TOP: 254px; HEIGHT: 24px" 
                      type="submit" value="Upload" runat="server" 
                      onserverclick="Upload_ServerClick" NAME="Upload">
        </form>
        <asp:label id="Label1" style="Z-INDEX: 106; LEFT: 46px; POSITION: absolute;
                      TOP: 326px" runat="server" Height="25px" 
                      Width="249px"></asp:label></span>
    </body>
</HTML>

And last but not least is the codebehind - attachme.aspx.cs The code-behind is very straightforward. AddFile_Click, RemvFile_Click and Upload_ServerClick are the three functions that are called.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;


namespace webchange
{
    /// <summary>

    /// attachme allows for multiple files to be uploaded to your web server while using 

    /// only one HttpInputFile control and a listbox.

    /// </summary>

    public class attachme : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.ListBox ListBox1;
        protected System.Web.UI.WebControls.Button AddFile;
        protected System.Web.UI.WebControls.Button RemvFile;
        protected System.Web.UI.HtmlControls.HtmlInputFile FindFile;
        protected System.Web.UI.HtmlControls.HtmlInputButton Upload;
        protected System.Web.UI.WebControls.Label Label1;
        protected System.Web.UI.HtmlControls.HtmlGenericControl txtOutput;
        public ArrayList files = new ArrayList();
                static public ArrayList hif = new ArrayList();
        public int filesUploaded = 0;
    
        private void Page_Load(object sender, System.EventArgs e)
        {
            // Put user code to initialize the page here

        
        }

        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //

            // CODEGEN: This call is required by the ASP.NET Web Form Designer.

            //

            InitializeComponent();
            base.OnInit(e);
        }
        
        /// <summary>

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary>

        private void InitializeComponent()
        {    
            this.RemvFile.Click += new System.EventHandler(this.RemvFile_Click);
            this.AddFile.Click += new System.EventHandler(this.AddFile_Click);
            this.Upload.ServerClick += new System.EventHandler(this.Upload_ServerClick);
            this.Load += new System.EventHandler(this.Page_Load);

        }
        #endregion

        /// <summary>

        /// AddFile will add the path of the client side file that is currently in the 

        /// PostedFile

        /// property of the HttpInputFile control to the listbox.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void AddFile_Click(object sender, System.EventArgs e)
        {
            if (Page.IsPostBack == true)
            {
                hif.Add(FindFile);
                ListBox1.Items.Add(FindFile.PostedFile.FileName);
            }
            else
            {
                
            }
        }

        /// <summary>

        /// RemvFile will remove the currently selected file from the listbox.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void RemvFile_Click(object sender, System.EventArgs e)
        {
            if(ListBox1.Items.Count != 0)
            {
                hif.RemoveAt(ListBox1.SelectedIndex);
                ListBox1.Items.Remove(ListBox1.SelectedItem.Text);
            }
        
        }

        /// <summary>

        /// Upload_ServerClick is the server side script that will upload the files to 

        /// the web server

        /// by looping through the files in the listbox.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        public void Upload_ServerClick(object sender, System.EventArgs e)
        {
            string baseLocation = "C:\\temp\\";
            string status = "";
            
            
            if((ListBox1.Items.Count == 0) && (filesUploaded == 0))
            {
                Label1.Text = "Error - a file name must be specified.";
                return;

            }
            else
            {
                foreach(System.Web.UI.HtmlControls.HtmlInputFile HIF in hif)
                {
                    try
                    {
                        string fn = System.IO.Path.GetFileName(HIF.PostedFile.FileName);
                        HIF.PostedFile.SaveAs(baseLocation + fn);
                        filesUploaded++;
                        status += fn + "<br>";
                    }
                    catch(Exception err)
                    {
                        Label1.Text = "Error saving file " + baseLocation
                                                           + "<br>" + err.ToString();
                    }
                }

                if(filesUploaded == hif.Count)
                {
                    Label1.Text = "These " + filesUploaded + " file(s) were "
                                           + "uploaded:<br>" + status;
                }
                hif.Clear();
                ListBox1.Items.Clear();
            }
        }

    }
}

AddFile_Click first checks to see if we are posting back to the page. If we are then it simply adds a copy of HttpInputFile FindFile to the hifArrayList. We are using the ArrayList to hold HttpInputFile objects. By holding them, as I will show shortly, we will have access to all of that object's methods and properties. The final line of AddFile_Click adds the fully qualified path of the file to the listbox.

private void AddFile_Click(object sender, System.EventArgs e)
{
    if (Page.IsPostBack == true)
    {
        hif.Add(FindFile);
        ListBox1.Items.Add(FindFile.PostedFile.FileName);
    }
    else
    {
    
    }
}
RemvFile_Click first ensures that there are items in the listbox to remove, then removes the selected item from the ArrayList and the ListBox.
private void RemvFile_Click(object sender, System.EventArgs e)
{
    if(ListBox1.Items.Count != 0)
    {
        hif.RemoveAt(ListBox1.SelectedIndex);
    ListBox1.Items.Remove(ListBox1.SelectedItem.Text);
    }
}
Upload_ServerClick is the heart of the form. First we set the destination variable's, baseLocation, path. This is the location on the web server where the file will be uploaded to. Next we ensure that there are files to be uploaded. Assuming that there are loop through the items in the ArrayList hif extracting the filename from each path and appending it to the baseLocation variable. Call the SaveAs method of the HttpInputFile control and pass it the path and filename to upload to the server. Of course we will check for errors and will handle them accordingly. Lastly explicitly clear the ArrayList hif. Since this is a static variable we want to ensure that its contents have been removed from memory so as not to duplicate and overwrite files on the server. Clear the listbox. You are done. Check the server to make sure the files are there and are of the proper size.

public void Upload_ServerClick(object sender, System.EventArgs e)
{
    string baseLocation = "C:\\temp\\";
    string status = "";
    
    if((ListBox1.Items.Count == 0) && (filesUploaded == 0))
    {
        Label1.Text = "Error - a file name must be specified.";
        return;
    }
    else
    {
        foreach(System.Web.UI.HtmlControls.HtmlInputFile HIF in hif)
        {
            try
            {
                string fn = System.IO.Path.GetFileName(HIF.PostedFile.FileName);
                HIF.PostedFile.SaveAs(baseLocation + fn);
                filesUploaded++;
                status += fn + "<br>";
            }
            catch(Exception err)
            {
                Label1.Text = "Error saving file " + baseLocation +  "<br>"
                                                   + err.ToString();
            }
        }

        if(filesUploaded == hif.Count)
        {
            Label1.Text = "These " +  filesUploaded + " file(s) were uploaded:<br>" 
                                                    + status;
        }
        hif.Clear();
        ListBox1.Items.Clear();
    }
}

Conclusion

There really is no great magic behind this code. In fact it might not even be the best way to accomplish this. For now though hopefully it will help others as much as it has helped me.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here