65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 MultiUpload 和 ImageList 服务器控件进行专业文件上传

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.80/5 (2投票s)

2007年12月20日

GPL3

5分钟阅读

viewsIcon

53663

downloadIcon

499

一个专业的 AJAX GUI,用于使用 Memba Velodoc XP Edition 中的服务器控件上传文件。

MultiUpload2 and ImageList in run mode

引言

ImageList 和 MultiUpload 最近在两篇文章中被介绍过

我们的目标是实现一个专业的 GUI 来上传文件,这通过结合 ImageListMultiUpload 来实现。我们的环境是 ASP.NET 2.0 (Windows 和 IIS),我们的 ImageListMultiUpload 控件都使用了 ASP.NET AJAX Extensions 1.0,您可以从此处下载并安装。

背景

本文引用了“Memba Velodoc XP Edition”的开源控件,您可以从此处下载(此页面提供 Codeplex、Google Code 和 Sourceforge.NET 的链接),它们以 GPL 许可分发。这些控件包括 ImageListMultiUpload 控件,我们在本文中使用它们。您可以此链接现场体验这些控件。

使用代码

在 Visual Studio 2005 中,创建一个新的 ASP.NET AJAX 启用网站,并添加对 Memba.WebControls.XP.dll 的引用,其中包含 ImageListMultiUpload2 服务器控件。Memba.WebControls.XP.dll 是 Memba Velodoc XP Edition 的一部分。源代码可在上述下载位置找到。

打开 Default.aspx 页面,并添加 ImageListMultiUpload2 服务器控件,方法是将控件添加到工具箱后拖放,或者简单地在现有的 <form> 标签之间添加以下代码

<form id="form1" runat="server" enctype="multipart/form-data">
<asp:ScriptManager ID="ScriptManager" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/scripts/Memba.Utils.js" />
    </Scripts>
</asp:ScriptManager>
<!-- MultiUpload2 -->
<mbui:MultiUpload2 ID="MultiUpload" runat="server"
    Text="Choose file..."
    Width="100px"
    CssClass="cssMultiUpload"
    HoverCssClass="cssMultiUploadHover">
</mbui:MultiUpload2>
<!-- MultiUpload2 -->
<!-- ImageList -->
<mbui:ImageList ID="ImageList" runat="server"
    CssClass="cssList"
    ItemCssClass="cssItem"
    ItemHoverCssClass="cssItemHover"
    ImageCssClass="cssImage"
    TextCssClass="cssText"
    RemoveCssClass="cssRemove"
    RemoveTooltip="Remove from selection"
    LinesOfText="2"
    Height="92px"
    Width="420px">
</mbui:ImageList>
<!-- ImageList -->
<input type="button" id="ClearButton" value="Clear" onclick="onClear();" />
<asp:Button ID="SubmitButton" runat="server" Text="Submit" OnClick="SubmitButton_Click" />
</form>

此表单还包括一个 HTML 按钮 (ClearButton) 和一个 ASP.NET 提交按钮 (SubmitButton)。

您可能需要在页面顶部使用以下语句注册标签前缀

<%@ Register Assembly="Memba.WebControls.XP" 
    Namespace="Memba.WebControls" TagPrefix="mbui" %> 

请确保您添加了对 Memba.Utils.js 的脚本引用,其中包含创建 JavaScript GUID 所必需的实用函数。

为了使文件上传正常工作,您需要进行两项重要设置

  1. form 标签上定义 enctype="multipart/form-data"
  2. web.config<system.web> 部分添加一个 httpRuntime 部分。这在引言中引用的文章中有详细描述。

用于呈现 ImageListMultiUpload 的内联 CSS 样式也在相应的文章中有描述。添加样式后,您的设计模式下的页面应如下所示

MultiUpload2 and ImageList in design mode

现在我们的页面已设计完成,我们需要代码来保存已发布的文件。双击提交按钮 (btnSubmit) 以在 Default.aspx.cs 中实现服务器端 Click 事件处理程序

private const string TARGET_DIR = "~/";
 
protected void SubmitButton_Click(object sender, EventArgs e)
{
    //Check target directory
    string sTargetDir = Request.MapPath(TARGET_DIR);
    System.Diagnostics.Debug.Assert(Directory.Exists(sTargetDir));
 
    //Iterate through posted files
    for (int i = 0; i < Request.Files.Count; i++)
    {
        HttpPostedFile objFile = Request.Files[i];
        //Make sure file input has content
        if ((objFile.ContentLength > 0) && (objFile.FileName.Length > 0))
        {
            //Get target file path for save as
            string sFileName = Path.GetFileName(objFile.FileName);
            string sFilePath = Path.Combine(sTargetDir, sFileName);
            FileInfo objFileInfo = new FileInfo(sFilePath);
            //No business rule, i.e. we just want to avoid failure
            if (objFileInfo.Exists)
            {
                objFileInfo.Attributes &= ~FileAttributes.ReadOnly;
                objFileInfo.Delete();
            }
            //Save file
            objFile.SaveAs(sFilePath);
        }
    }
    //Clear the list, otherwise the ImageList has items
    //Which the MuliUpload component does not have
    ImageList.ImageListItemCollection.Clear();
}

在文件顶部添加以下语句

using System.IO; //Directory, Path, FileInfo 

这里需要注意的关键是,浏览器每次加载页面时都会清除 HTML 文件输入控件,尤其是在回发后。无法设置文件输入控件的值,否则 Web 服务器可以在未经用户同意的情况下获取用户文件。对此安全限制没有变通方法。我们的 ImageList 被设计为保持其状态,因此需要清除它以与 MultiUpload 控件同步。

此时我们可以运行页面并上传文件,但我们需要一些 JavaScript 客户端代码来在 ImageList 中显示已在 MultiUpload 控件中选择的文件。在页面的 </body> 结束标签之前添加以下脚本

<script type="text/javascript">
<!--
// Declare global variables for the various controls
var g_MultiUpload;
var g_ImageList;
//pageLoad function of ASP.NET Ajax Extensions framework
function pageLoad()
{
    //Get a reference to the MultiUpload control and
    //add en event handler for the browse event
    g_MultiUpload = $find("<%= MultiUpload.ClientID %>");
    if(g_MultiUpload)
        g_MultiUpload.add_browse(onBrowse);
    //Get a reference to the ImageList control and
    //add en event handler for the browse event
    g_ImageList = $find("<%= ImageList.ClientID %>");
    if(g_ImageList)
        g_ImageList.add_remove(onRemove); 
}
//pageLoad function of ASP.NET Ajax Extensions framework
function pageUnload()
{
    if(g_MultiUpload)
        g_MultiUpload.remove_browse(onBrowse);
    if(g_ImageList)
        g_ImageList.remove_remove(onRemove); 
}
//Event handler for the browse (click) event of the MultiUpload control
function onBrowse(sender, args)
{
    if((g_ImageList) && (g_MultiUpload))
    {
        //Search for the item in the Imagelist
        if (g_ImageList.find_item(args.get_value()).length > 0)
        {
            alert("file already in list");
            //The item already exists,
            //we can remove the duplicate INPUT in the MultiUpload control
            g_MultiUpload.removeInput(args.get_id());
        }
        else
        {
            //Since the item is not found in the ImageList,
            //create a new item
            var item = new Memba.WebControls.ImageListItem(
                Memba.Utils.newGuid(),
               '<%= this.ResolveClientUrl("~/images/upload.gif") %>',
               args.get_value(),
               args.get_value(),
               args.get_id()
               );
            //Add the new item to the ImageList
            g_ImageList.add_item(item);
        }
        //We can do some tracing which will display in the TraceConsole textarea 
        Sys.Debug.trace(g_ImageList.get_count()
            + " files in image list, and " + g_MultiUpload.get_count()
            + " files in MultiUpload control");
    }
}
//Event handler for the remove event of the ImageList control
function onRemove(sender, args)
{
    if((g_ImageList) && (g_MultiUpload))
    { 
        //Upon clicking the remove icon in the ImageList,
        //remove the corresponding INPUT in the MultiUpload control
        g_MultiUpload.removeInput(args.get_tag());
        //We can do some tracing which will display in the TraceConsole textarea 
        Sys.Debug.trace(g_ImageList.get_count()
            + " files in image list, and " + g_MultiUpload.get_count()
            + " files in MultiUpload control");
    }
}
//Event handler for the click event of the clear button
function onClear()
{
    if(g_MultiUpload)
        g_MultiUpload.clear();
    if(g_ImageList)
        g_ImageList.clear();
}
//-->
</script>

ASP.NET AJAX 扩展提供了两个重要的 JavaScript 事件处理程序

  • pageLoad 由框架在页面 DOM 和脚本加载并初始化时调用。这是一个获取控件引用和添加事件处理程序的理想位置。
  • pageUnload 由框架在页面卸载时调用。建议在此阶段清除处理程序。

上面的脚本实现了 MultiUpload 控件的 Browse 事件、ImageList 控件的 Remove 事件以及 Clear 按钮的 Click 事件的处理程序。Browse 事件处理程序将选定的文件添加到 ImageListImageList 项有一个名为 tag 的属性,该属性设置为 MultiUpload 控件中文件输入的标识符。Remove 事件处理程序读取从 ImageList 中移除的项的 tag,以从 MultiUpload 控件中移除相应的文件输入。Clear 事件处理程序仅清除 ImageListMultiUpload 控件。

按 F5 运行项目,然后单击标有“Choose file...”的 MultiUpload 控件将文件添加到列表中。将鼠标移到 ImageList 中相应的项上,以显示移除图标(一个红色的叉)。单击移除图标以从上传选择中移除相应的文件。添加更多文件。测试 Clear 按钮。添加文件并提交以上传文件。

此时,完成一个专业的上传页面将需要一个进度指示器。我们建议阅读使用 Ajax 显示 ASP.NET 服务器任务的进度。如果您想将所有这些控件结合在一起,我建议下载 Memba Velodoc XP Edition 的源代码和其中包含的开发者教程,这将帮助您进入下一个阶段。

关注点

这个 MultiUpload 控件隐藏了动态创建文件输入 HTML 控件的复杂性,并消除了对已选择上传文件的呈现的任何限制。与 ImageList 控件的结合是我们在此描述的一个绝佳的呈现选项,它比旧的、丑陋的文件输入控件有了巨大的改进。对于更高级的开发人员,ImageListMultiUpload 控件的源代码可在 CodeplexGoogle CodeSourceforge.NET 上找到,并且进行了非常详细的注释。

历史

  • 版本 1.0 - 日期 2007 年 12 月 20 日。
使用 MultiUpload 和 ImageList 服务器控件进行专业的ファイル上传 - CodeProject - 代码之家
© . All rights reserved.