你的位置:首页 > ASP.net教程

[ASP.net教程]多附件上传控件

以前写过一个单页面多类型的多附件上传,但是在实际项目中,这样的并不多见,相比之下,多附件上传却经常用到。

于是,就像自己创建一个用户控件,用来上传多附件。

话不多说,先看下界面吧。

设计时

运行后

先说下界面吧,上下两个repeater,分别用于编辑和查看时使用。上面的repeater,带有删除按钮,用于编辑时可以删除不要的附件;下面的repeater,用于查看是使用,如果没有上传附件,则给控件Literal赋值空格符( ),用于浏览器兼容问题。

中间的上传控件,不用多说,用于上传附件;后面添加按钮,使用JS动态创建上传控件,以便能够上传多个附件;下面的隐藏控件,前期用于记录创建的上传的控件个数,点击提交按钮后用于保存上传的附件路径,以便数据保存失败时删除附件。

 

下面我们来看下前台的html代码。

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AttaUpload.ascx.cs"  Inherits="WEB.webcontrols.AttaUpload" %><script src="../js/AttaUpload.js" type="text/javascript"></script><div id="tabEdit" runat="server">  <asp:Repeater ID="rpFileE" runat="server" OnItemCommand="rpFile_ItemCommand">    <ItemTemplate>      <div>        <asp:LinkButton ID="lbn_load" CommandArgument='<%#Eval("ID") %>' CommandName="load"          runat="server" ><%# Eval("FileName").ToString() + Eval("FileType").ToString()%></asp:LinkButton>&emsp;&emsp;&emsp;        <asp:LinkButton ID="lbtn_del" Style="color: Blue" CommandArgument='<%#Eval("ID") %>'          CommandName="del" runat="server" OnClientClick='<%#"return DelMsg(\"「"+Eval("FileName").ToString() + Eval("FileType").ToString()+"」\")" %>'>删除</asp:LinkButton>      </div>    </ItemTemplate>  </asp:Repeater>  <div id="atta" runat="server">    <asp:FileUpload ID="fufile" runat="server" onchange="if(this.value)JudgeFile(this.value,this);" />    <asp:ImageButton ID="imgbtn_add" runat="server" src="../images/add.gif" Style="margin-bottom: -2px;" />  </div>  <asp:HiddenField ID="hffile" runat="server" Value="1" /></div><div id="tabView" runat="server" visible="false">  <asp:Repeater ID="rpFileV" runat="server" OnItemCommand="rpFile_ItemCommand">    <ItemTemplate>      <div>        <asp:LinkButton ID="lbn_load" CommandArgument='<%#Eval("ID") %>' CommandName="load"          runat="server" ><%# Eval("FileName").ToString() + Eval("FileType").ToString()%></asp:LinkButton>      </div>    </ItemTemplate>  </asp:Repeater>  <asp:Literal ID="ltlfile" runat="server"></asp:Literal></div>

View Code

其中AttaUpload.js文件,就是该控件用到的所有JS代码所在,里面包含有动态创建上传控件,删除附件提示,删除动态创建的上传控件等等相关功能的JS编码。

/**********动态添加上传附件**********/function AddAtta(id, hfid) {  //var hfid = jQuery("#" + id).next().attr('id'); //document.getElementById(id).nextSibling.id;(IE10不兼容)  var d = document.createElement("div");  var f = document.createElement("input");  f.setAttribute("type", "file");  f.setAttribute("name", "upfile");  f.setAttribute("style", "margin-top:5px;");  f.onchange = function () {    if (this.value) JudgeFile(this.value, this);  }  d.appendChild(f);  //添加删除按钮  var im = document.createElement("img");  im.setAttribute("src", "../images/close.gif");  im.style.cssText = "margin-left:3px;margin-bottom: -2px;cursor:pointer";  im.onclick = function () {    document.getElementById(hfid).value = $val(hfid) - 1;    return DelFile(this, "DIV");  }  d.appendChild(im);  document.getElementById(id).appendChild(d);  //添加计数  document.getElementById(hfid).value = parseInt($val(hfid)) + 1;  return false;}/**********删除**********/function DelFile(f, name) {  while (f.tagName != name)    f = f.parentNode;  f.parentNode.removeChild(f);  return false;}/**********判断文件类型和大小**********/function JudgeFile(file, node) {  var typelist = ["txt", "doc", "xls", "ppt", "docx", "xlsx", "pptx", "pdf", "jpeg", "jpg", "png", "bmp", "gif"];  if (file) {    var match = 0;    var suffix = file.split(".");    var num = suffix.length - 1;    var name = suffix[num].toLowerCase();    for (var i = 0; i < typelist.length; i++) {      if (name == typelist[i]) {        match = 1;        break;      }    }    if (match != 1) {      alert("暂不支持上传该类型的文件,请重新选择!");      node.outerHTML = node.outerHTML;    }  }  getFileSize(node);}//判断文件大小function getFileSize(obj) {  var size = 0;  if (navigator.userAgent.indexOf("MSIE") > 0) {    try {      var fso = new ActiveXObject('Scripting.FileSystemObject'); //获取上传文件的对象      var file = fso.GetFile(obj.value);      size = file.Size;    }    catch (err) {      size = 0;    }  } else {    size = obj.files[0].size;  }  if ((size / 1048576) > 40) {    alert("上传文件大于40M,无法上传!");    obj.outerHTML = obj.outerHTML;  }}/**********删除信息提示框**********/function DelMsg(mess) {  return confirm("系统提示:您确认删除" + mess + "吗?");}

View Code


现在我们来看下控件的后台编码:

1、参数:

/// <summary>    /// 项目ID    /// </summary>    public string ProID    {      get      {        if (ViewState["AttaProID"] == null)        {          return "";        }        else        {          return (string)ViewState["AttaProID"];        }      }      set      {        ViewState["AttaProID"] = value;      }    }    /// <summary>    /// 控件ID    /// </summary>    public string WucID    {      get      {        if (ViewState["AttaWucID"] == null)        {          return "AttaUp";        }        else        {          return (string)ViewState["AttaWucID"];        }      }      set      {        ViewState["AttaWucID"] = value;      }    }    /// <summary>    /// 查看或编辑(0:编辑;1:查看)    /// </summary>    public string Flag    {      get      {        if (ViewState["AttaFlag"] == null)        {          return "0";        }        else        {          return (string)ViewState["AttaFlag"];        }      }      set      {        ViewState["AttaFlag"] = value;      }    }

View Code

2、页面加载:

/// <summary>/// 加载/// </summary>/// <param name="sender"></param>/// <param name="e"></param>protected void Page_Load(object sender, EventArgs e){  if (!IsPostBack)  {    imgbtn_add.Attributes.Add("onclick", "return AddAtta('" + WucID  + "_atta','" + WucID + "_hffile')");    //页面附件绑定   if (ProID != "")    {      //读取现有数据    InitData();    }  }}

View Code

  关于在后台给“添加”按钮绑定JS方法,是为了要把控件的ID传到前台,否则“动态创建上传控件”和“保存累计个数”的方法就不能使用了。

  而如果id="atta"的div不加上runat="server"的话,那任何页面就只能使用一次了。

3、绑定数据:

    /// <summary>    /// 读取数据    /// </summary>    private void InitData()    {      PrjFileEntity model = new PrjFileEntity();      model.ProID = ProID;      model.FileFlag = -2;      DataView dv = PrjFileBLL.GetContact(model).DefaultView;      if (Flag == "0")      {        // 编辑数据        rpFileE.DataSource = dv;        rpFileE.DataBind();      }      else      {        // 查看数据        rpFileV.DataSource = dv;        rpFileV.DataBind();        tabEdit.Visible = false;        tabView.Visible = true;        if (dv == null || dv.Count <= 0)        {          ltlfile.Text = "&nbsp;";        }      }    }

View Code

4、保存附件:

    /// <summary>    /// 保存附件    /// </summary>    /// <param name="proid"></param>    public PrjFileEntity Save(int start, string path, string ucid)    {      int one = Convert.ToInt32(hffile.Value);      PrjFileEntity filemodel = CommonFunction.FileUpLoad(start, one + start, hffile, path, ucid, (int)CommonEnum.FileFlag.上传);      if (filemodel.ID == "-2")      {        CommonFunction.delfile(hffile.Value.ToString());        hffile.Value = "1";        ShowMessages(filemodel.FileName);        return null;      }      else      {        return filemodel;      }    }

View Code
    /// <summary>    /// 项目文档上传文件    /// </summary>    /// <param name="start">起始值</param>    /// <param name="end">终止值</param>    /// <param name="hfcount">隐藏控件</param>    /// <param name="url">路径(例:project/123)</param>    /// <param name="ucid">用户控件ID(UserContronlID)</param>    /// <param name="fileflag">附件标识(CommonEnum.FileFlag)</param>    /// <returns></returns>    public static PrjFileEntity FileUpLoad(int start, int end, HiddenField hfcount, string url, string ucid, int fileflag)    {      int upsize = 40000000;      try      {        upsize = Convert.ToInt32(ConfigurationManager.AppSettings["upsize"].ToString());      }      catch (Exception)      {        upsize = 40000000;      }      //清空隐藏控件的值,用于存放路径      if (hfcount != null)      {        hfcount.Value = "";      }      //设置上传路径      string path = System.Web.HttpContext.Current.Server.MapPath("~/UpFile/" + url + "/");      //判断上传文件夹是否存在,若不存在,则创建      if (!Directory.Exists(path))      {        //创建文件夹        Directory.CreateDirectory(path);      }      string attaname = "";      string attaurl = "";      string attatype = "";      PrjFileEntity accessinfo = null;      HttpFileCollection files = HttpContext.Current.Request.Files;      for (int i = start; i < end; i++)      {        HttpPostedFile postedFile = files[i];        if (postedFile.FileName != "")        {          if (postedFile.ContentLength < upsize)          {            string[] name = postedFile.FileName.ToString().Split('\\');            //获取扩展名            string extname = System.IO.Path.GetExtension(postedFile.FileName);            //获取上传文件的名称            string oglname = name[name.Length - 1].ToString().Replace(extname, "");            //存储上传的文件名            attaname += oglname + ",";            attatype += extname + ",";            //为上传的文件设置新的名称,防止重名            string newname = System.DateTime.Now.ToString("yyyyMMddHHmmssffff") + i.ToString();            newname = newname + extname;            //设置完整的文件上传路径            string filepath = path + newname;            postedFile.SaveAs(filepath);            if (hfcount != null)            {              hfcount.Value += filepath + "$";            }            int j = filepath.IndexOf("UpFile");            string str = filepath.Substring(j - 1);            attaurl += "~" + str + ",";          }          else          {            accessinfo = new PrjFileEntity();            accessinfo.ID = "-2";            accessinfo.FileName = "上传失败,上传文件不能大于" + upsize / 1000000 + "M!";            return accessinfo;          }        }      }      attatype = attatype.TrimEnd(',');      attaname = attaname.TrimEnd(',');      attaurl = attaurl.TrimEnd(',');      if (attaname != "" && attaurl != "" && attatype != "")      {        accessinfo = new PrjFileEntity(attatype, attaname, attaurl, ucid, fileflag);      }      else      {        accessinfo = new PrjFileEntity();      }      return accessinfo;    }

View Code

5、删除附件:

    /// <summary>    /// 删除附件    /// </summary>    public void Delete()    {      CommonFunction.delfile(hffile.Value.ToString());      hffile.Value = "1";    }

View Code

6、附件下载及删除:

    /// <summary>    /// 附件下载及删除    /// </summary>    /// <param name="source"></param>    /// <param name="e"></param>    protected void rpFile_ItemCommand(object source, RepeaterCommandEventArgs e)    {      string id = e.CommandArgument.ToString().Trim();      PrjFileEntity fileinfo = PrjFileBLL.GetUniqueObj(id);      string path = fileinfo.FilePath;      if (e.CommandName.ToString() == "del")      {        path = HttpContext.Current.Server.MapPath(path);        bool istrue = PrjFileBLL.Delete(id);        if (istrue)        {          //物理路径的文件删除          if (System.IO.File.Exists(path))          {            System.IO.File.Delete(path);          }          ShowMessages("删除成功");          //InitData();          //表单附件绑定          if (WorkTaskInsID != "")          {            FormData();          }          //页面附件绑定          else if (ProID != "")          {            //读取现有数据            InitData();          }        }        else        {          ShowMessages("删除失败");        }      }      else      {        ShowScript("AttaView(\"" + id + "\",1)");      }    }

View Code

7、消息提醒:

    /// <summary>    /// 消息提醒    /// </summary>    /// <param name="sMessage"></param>    private void ShowMessages(string sMessage)    {      Page.ClientScript.RegisterStartupScript(this.GetType(), "Message", "<script>alert('系统提示:" + sMessage + "!');</script>");      return;    }    /// <summary>    /// 运行纯脚本    /// </summary>    /// <param name="sMessage"></param>    public void ShowScript(string script)    {      Page.ClientScript.RegisterStartupScript(GetType(), "", script, true);    }

View Code

8、获取隐藏控件的计数:

    /// <summary>    /// 获取隐藏控件的数值    /// </summary>    /// <returns></returns>    public int GetHiddenCount()    {      return Convert.ToInt32(hffile.Value);    }

View Code

  此方法在页面调用两个或两个以上此控件的时候使用。

 

最后看下调用:

1、在webconfig中注册:

 <add src="~/webcontrols/AttaUpload.ascx" tagName="AttaUp" tagPrefix="wuc"/>

2、页面前台调用:

    <tr>      <th>        附件      </th>      <td colspan="3">        <wuc:AttaUp ID="AttaUp" runat="server" />      </td>    </tr>

3、页面加载时传递参数:

//附件AttaUp.ProID = CID;//查看时才传,编辑时不需要AttaUp.Flag = "1";

4、提交页面时调用:

 PrjFileEntity filemodel = AttaUp.Save(0, CommonFunction.GetProjectPath(hfproid.Value), "");

  第一参数“0”,表示是从第一个上传控件开始查找附件;如果有两个上传控件,那么第一个控件保存附件时,传“0”;第二个则要用第一控件的GetHiddenCount()方法,获取第一个控件的上传控件个数;如果有第三个控件,那就要“累加”第一个控件和第二个控件的GetHiddenCount()方法的返回值。以此类推!!

5、页面数据保存失败时调用:

AttaUp.Delete();//删除上传的附件

 

写在最后:AttaUpload.js中我把判断附件大小的JS方法去掉了,