Introduction
The HTML file input control and the ASP.NET FileUpload
control derived from it have important limitations including poor graphic design and security restrictions. Our objective is to provide a better file upload component. This function is fulfilled by a MultiUpload
control, which improves on Google mail’s file attachment experience. Our environment is ASP.NET 2.0 on Windows and IIS, and our MultiUpload
control uses ASP.NET AJAX Extensions 1.0, which you can download and install from here.
Background
This article refers to the open-source controls of “Memba Velodoc XP Edition”, which you can download from here (this page provides links to Codeplex, Google code, and Sourceforge.NET) and which are distributed under the GPL license. These controls include a MultiUpload
control which we use in this article. You can experiment these controls live at this link.
Using the code
In Visual Studio 2005, create a new ASP.NET AJAX-Enabled Web Site, and add a reference to Memba.WebControls.XP.dll which contains the MultiUpload
and MultiUpload2
server controls. Memba.WebControls.XP.dll is part of Memba Velodoc XP Edition. The source code is available at the download location cited above.
MultiUpload
and MultiUpload2
expose the same properties and methods. Only the implementation is different:
MultiUpload
was our first attempt to execute this control based on an anchor tag. Clicking the anchor tag triggers a Click
event on an invisible file input control. Unfortunately, file inputs do not implement the Click
method in Firefox, so this control only works in Internet Explorer.MultiUpload2
is our second attempt to execute this control. MultiUpload2
is a span
tag with a file input positioned on top of it. Note that the span
tag could easily be replaced by a button or an image. The opacity of the file input is set to 0 so that it is invisible, but can receive the Click
event on the Browse button. Each time a file input is filled, it is moved to a hidden location and replaced by a new one in order to permit multiple uploads.
Open the Default.aspx page and add the MultiUpload2
server control, either by dragging and dropping the control after adding it to the toolbox, or simply by adding the following code between the existing <form>
tags:
<form id="form1" runat="server" enctype="multipart/form-data">
<asp:ScriptManager ID="ScriptManager" runat="server" />
<mbui:MultiUpload2 ID="MultiUpload" runat="server"
Text="Click me"
CssClass="cssMultiUpload"
HoverCssClass="cssHoverMultiUpload">
</mbui:MultiUpload2>
<hr />
<div id="divDisplay" style="min-height:50px;">
<asp:Literal ID="litDisplay" runat="server"></asp:Literal>
</div>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnSubmit_Click" />
</form>
The form also includes a div
(divDisplay
) containing an ASP.NET Literal
(litDisplay
) and an ASP.NET submit button (btnSubmit
).
You may have to register the tag prefix at the top of the page, using the following statement:
<%@ Register Assembly="Memba.WebControls.XP"
Namespace="Memba.WebControls" TagPrefix="mbui" %>
For file uploads to work, you need to make two important settings:
- Define
enctype="multipart/form-data"
on the form
tag; - Add an
httpRuntime
section to the <system.web>
section of your web.config, with the following attributes:
<httpRuntime maxRequestLength="1000000" executionTimeout="20000"/>
maxRequestLength
defines the maximum size of the post request in kilobytes. The ASP.NET default is 4096, which limits the size of a post request to 4 MB. executionTimeout
defines the maximum duration of a request in seconds. It is advised to limit such settings to specific pages, using <location>
sections in web.config.
From the standpoint of presentation, the MultiUpload2
control is a SPAN
. Add the following styles just above the </head>
closing tag of your page:
<style type="text/css">
<!--
.cssMultiUpload{
color:CornflowerBlue;
text-decoration:none;
}
.cssHoverMultiUpload{
color:CornflowerBlue;
text-decoration:underline;
}
</style>
Your MultiUpload2
control should now look like:
Now that our page is designed, we need the code to save the posted files. Double click the Submit button (btnSubmit
) to implement the server-side Click
event handler in Default.aspx.cs:
private const string TARGET_DIR = "~/";
protected void btnSubmit_Click(object sender, EventArgs e)
{
string sTargetDir = Request.MapPath(TARGET_DIR);
System.Diagnostics.Debug.Assert(Directory.Exists(sTargetDir));
StringBuilder objDisplay = new StringBuilder();
objDisplay.Append("<h3>You have just saved:</h3><ul>");
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFile objFile = Request.Files[i];
if ((objFile.ContentLength > 0) && (objFile.FileName.Length > 0))
{
string sFileName = Path.GetFileName(objFile.FileName);
string sFilePath = Path.Combine(sTargetDir, sFileName);
FileInfo objFileInfo = new FileInfo(sFilePath);
if (objFileInfo.Exists)
{
objFileInfo.Attributes &= ~FileAttributes.ReadOnly;
objFileInfo.Delete();
}
objFile.SaveAs(sFilePath);
objDisplay.AppendFormat("<li><a href=\"{0}\">{1}</a></li>",
this.ResolveUrl(Path.Combine(TARGET_DIR, sFileName)), sFileName);
}
}
objDisplay.Append("</ul>");
litDisplay.Text = objDisplay.ToString();
}
Add the following statements at the top of Default.aspx.cs:
using System.IO;
using System.Text;
Press F5 to run the page, click the MultiUpload
control labeled “Click me” to add a file, and click the Submit button. The response should display links to download the files which have just been uploaded.
We would now like to display the names of the files as they are selected. Add the following script just before the </body>
closing tag of your page.
<script type="text/javascript">
<!--
var g_MultiUpload;
var g_Display = "<h3>You have selected:</h3><ul>";
function pageLoad()
{
g_MultiUpload = $find("<%= MultiUpload.ClientID %>");
if(g_MultiUpload)
g_MultiUpload.add_browse(onBrowse);
}
function pageUnload()
{
if(g_MultiUpload)
g_MultiUpload.remove_browse(onBrowse);
}
function onBrowse(sender, args)
{
g_Display += "<li>" + args.get_value() + "</li>";
$get("divDisplay").innerHTML = g_Display + "</ul>";
}
</script>
ASP.NET AJAX Extensions provide two important JavaScript event handlers:
pageLoad
is called by the framework when the page DOM and scripts are loaded and initialized. This is a good place to get references to controls and add event handlers.pageUnload
is called by the framework when the page unloads. It is recommended to clear handlers at this stage.
The script above implements an event handler for the browse
event of the MultiUpload
control. The browse
event handler adds the full name of the selected file to an unordered list which is displayed within the divDisplay
DIV
.
Press F5 to run the project, and click the MultiUpload
control labeled “Click me” to add a file. The page should now display a list of files as they are selected.
We would now want to interact with the list of selected files, especially to remove files, but this is the subject of a follow-up article entitled Professional file uploads with the MultiUpload and ImageList server controls.
Points of interest
This MultiUpload
control hides the complexity of dynamically creating file input HTML controls, and removes any constraint regarding the presentation of the files which have been selected for upload. For more advanced developers, the source code of the MultiUpload
control is available at Codeplex, Google code, and Sourceforge.NET, and is commented in great details.
History
- Version 1.0 - dated 19 Dec 2007