ASP.NET大文件断点上传

来源:互联网 发布:中国功夫 知乎 编辑:程序博客网 时间:2024/05/28 23:08

前端代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head id="Head1" runat="server">    <title></title>    <script language="javascript">        //全选        function CheckAll(e, itemname) {            var aa = document.getElementsByName(itemname);            if (aa == undefined) return;            for (var i = 0; i < aa.length; i++) aa[i].checked = e.checked;        }       </script>    <script language="javascript">        //判断复选框是否选中        function delss() {            var checkArray = document.getElementsByName("Item");            var checkNum = 0;            for (var i = 0; i < checkArray.length; i++) {                if (checkArray[i].checked) { checkNum++; }            }            if (checkNum == 0) {                alert('对不起,您还没有选择!');                return false;            }            else {                if (confirm("您确定要删除吗?")) {                    return true;                } else {                    return false;                }            }        }    </script></head><body>    <form id="form1" runat="server">    <asp:ScriptManager ID="ScriptManager1" runat="server">    </asp:ScriptManager>    <asp:Timer ID="Timer1" runat="server" Interval="1000" OnTick="Timer1_Tick">    </asp:Timer>    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">        <ContentTemplate>            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>        </ContentTemplate>        <Triggers>            <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="tick" />        </Triggers>    </asp:UpdatePanel>    <asp:FileUpload ID="FileUpload1" runat="server" />    <asp:Button ID="Button1" runat="server" Text="上传文件" OnClick="Button1_Click" />    <table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#cccccc">        <tr class="spgl_bg">            <td width="6%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">                <input name="chkall" value="1" type="checkbox" onclick="CheckAll(this,'Item')" class="qx" />全选            </td>            <td width="6%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">                编号            </td>            <td width="16%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">                名称            </td>            <td width="52%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">                上传文件地址            </td>            <td width="8%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">                已上传            </td>            <td width="12%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">                操作            </td>        </tr>        <asp:Repeater ID="rptList" runat="server">            <ItemTemplate>                <tr>                    <td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>">                        <input name="Item" type="checkbox" value='<%# Eval("fid")%>' />                    </td>                    <td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>">                        <%# Container.ItemIndex + 1 %>                    </td>                    <td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>"                        class="gml">                        <%# Eval("FileNameLocal")%>                    </td>                    <td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>"                        class="gml">                        <%# Eval("FilePathLocal")%>                    </td>                    <td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>"                        class="gml">                        <%# Eval("PostedPercent")%>                    </td>                    <td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>">                        <asp:LinkButton ID="lbTop" runat="server" Text='续传' CommandArgument='<%# Eval("fid") %>'                            OnCommand="lbTop_Click"></asp:LinkButton>|                        <asp:LinkButton ID="lbClose" Visible="false" runat="server" Text='停止' CommandArgument='<%# Eval("fid") %>'                            OnCommand="lbClose_Click"></asp:LinkButton>                        <asp:LinkButton ID="lbDel" runat="server" Text="删除" OnCommand="lbDel_Click" CommandArgument='<%# Eval("fid") %>'                            OnClientClick="javascript:return confirm('您确定要删除吗?');"></asp:LinkButton>                    </td>                    <asp:HiddenField ID="hidOK" runat="server" Value='<%# Eval("Isok") %>' />                </tr>            </ItemTemplate>        </asp:Repeater>    </table>    <asp:Button ID="btnAllDelete" runat="server" Text="批量删除" class="plsc" CommandName="delete"        OnClientClick="return delss()" OnCommand="btnAllDelete_Command" />    </form></body></html>

后端代码

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Web.demoSql.db;using System.IO;using System.Text;using System.Security.Cryptography;using System.Threading;namespace Web{    public partial class Index : System.Web.UI.Page    {        #region        public long m_FileSize;//文件总大小。        long m_RangePos;    //文件块起始位置        public long RangePos        {            set { this.m_RangePos = value; }        }        //文件读写锁,防止多个用户同时上传相同文件时,出现创建文件的错误        static ReaderWriterLock m_writeLock = new ReaderWriterLock();        #endregion        protected void Page_Load(object sender, EventArgs e)        {            if (!IsPostBack)            {                GetList();            }        }        /// <summary>        /// 上传事件        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected void Button1_Click(object sender, EventArgs e)        {            #region 获取上传文件的信息            string md5Fisrt = GenerateCheckCode10();            string uidFisrt = "0";            string fileLengthFisrt = FileUpload1.PostedFile.ContentLength.ToString();            string fileSizeFisrt = Math.Round(Convert.ToDouble(FileUpload1.PostedFile.ContentLength) / Convert.ToDouble(1024 * 1024), 2).ToString() + "MB";            string pathLocalFisrt = FileUpload1.PostedFile.FileName;            #endregion            string FileType = FileUpload1.FileName.Substring(FileUpload1.FileName.LastIndexOf(".") + 1);            if (FileUpload1.FileName == "" || Request.Files.Count < 0)            {                string msg = "请选择文件!";                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");            }            else if (FileType.ToLower() != "rar")            {                string msg = "文件格式不正确!";                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");                        }            else            {                #region 向数据库插入上传文件信息                HttpUploaderDB db = new HttpUploaderDB();                xdb_files inf = new xdb_files();                inf.FileNameLocal = Path.GetFileName(pathLocalFisrt);                inf.FilePathLocal = pathLocalFisrt;                inf.FileNameRemote = md5Fisrt + Path.GetExtension(pathLocalFisrt).ToLower();                //数据库存在相同文件                if (db.GetFileInfByMd5(md5Fisrt, ref inf))                {                    inf.FileNameLocal = Path.GetFileName(pathLocalFisrt);                    inf.FilePathLocal = pathLocalFisrt;                    inf.uid = int.Parse(uidFisrt);//将当前文件UID设置为当前用户UID                    inf.IsDeleted = false;                    inf.fid = db.Add(ref inf);                }//数据库不存在相同文件                else                {                    HttpUploaderCfg cfg = new HttpUploaderCfg();                    cfg.CreateUploadPath();                    inf.uid = int.Parse(uidFisrt);//将当前文件UID设置为当前用户UID                    inf.FileSize = fileSizeFisrt;                    inf.FileMD5 = md5Fisrt;                    inf.FileLength = Convert.ToInt32(fileLengthFisrt);                    inf.FilePathRemote = Path.Combine(cfg.GetUploadPath(), inf.FileNameRemote);                    inf.FilePathRelative = Path.Combine(cfg.GetRelatPath(), inf.FileNameRemote);                    inf.fid = db.Add(ref inf);                    GetList();                }                #endregion                #region 更新上传进度                int num = 0;                string struid = uidFisrt;                string strfid = inf.fid.ToString();                string strFileSize = fileLengthFisrt;                string strRangePos = num.ToString();                if (strFileSize.Length > 0                    && struid.Length > 0                    && strfid.Length > 0                    && md5Fisrt.Length > 0                    && strRangePos.Length > 0                    && Request.Files.Count > 0)                {                    long fileSize = Convert.ToInt64(strFileSize);                    long rangePos = Convert.ToInt64(strRangePos);                    int uid = Convert.ToInt32(struid);                    int fid = Convert.ToInt32(strfid);                    //临时文件大小                    HttpPostedFile file = Request.Files.Get(0);                    long rangeSize = 131072;                    long rangeSiHH = 131072;                    xdb_files infModel = new xdb_files();                    for (long i = 0; i <= Convert.ToInt32(file.InputStream.Length); )                    {                        if (db.GetFileInfByFid(fid, ref infModel))                        {                            //已上传大小 = 文件块索引 + 临时文件块大小                            //long postedLength = rangePos + rangeSize;                            long postedLength = i + rangeSize;                            long nownum = i;                            if (file.InputStream.Length < postedLength)                            {                                postedLength = file.InputStream.Length - nownum;                                rangeSiHH = file.InputStream.Length - nownum;                            }                            //上传百分比 = 已上传大小 / 文件总大小                            double per = ((double)postedLength / (double)fileSize) * 100;                            decimal perd = Math.Round((decimal)per, 2);                            string postedPercent = perd.ToString() + "%";                            //保存文件块数据                            FileResumer res = new FileResumer();                            res.m_FileSize = fileSize;//根据客户端文件大小在服务端创建文件                            res.RangePos = rangePos;                            #region                            m_writeLock.AcquireWriterLock(1000);                            //文件不存在则创建                            if (!File.Exists(infModel.FilePathRemote))                            {                                FileStream fs = File.OpenWrite(infModel.FilePathRemote);                                BinaryWriter w = new BinaryWriter(fs);                                for (long ii = 0; ii < infModel.FileLength; ++ii)                                {                                    w.Write((byte)0);                                }                                w.Close();                                fs.Close();                            }                            m_writeLock.ReleaseWriterLock();                            //上传的文件大小不为空                            if (rangeSiHH > 0)                            {                                //文件已存在,写入数据                                //可能会有多个线程同时写文件。                                FileStream fs = new FileStream(infModel.FilePathRemote, FileMode.Open, FileAccess.Write, FileShare.Write);                                fs.Seek(i, SeekOrigin.Begin);                                byte[] ByteArray = new byte[rangeSiHH];                                file.InputStream.Read(ByteArray, 0, (int)rangeSiHH);                                fs.Write(ByteArray, 0, (int)rangeSiHH);                                fs.Flush();                                fs.Close();                            }                            #endregion                            //更新文件进度                            db.UpdateProgress(uid, fid, rangePos, postedLength, postedPercent);                            i += rangeSize;                        }                    }                }                #endregion                #region 上传完成                db.UploadComplete(md5Fisrt);                #endregion                GetList();            }                    }        /// <summary>        /// 续传        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected void lbTop_Click(object sender, CommandEventArgs e)        {            int id = Convert.ToInt32(e.CommandArgument);            HttpUploaderDB db = new HttpUploaderDB();            #region 设置按钮状态            foreach (RepeaterItem grv in rptList.Items)            {                LinkButton lb1 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbTop");//续传                LinkButton lb2 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbClose");//停止                lb1.Enabled = false;                lb2.Enabled = false;            }            LinkButton t = (LinkButton)sender;            RepeaterItem ri = (RepeaterItem)t.NamingContainer;            LinkButton itemid = ((LinkButton)ri.FindControl("lbClose"));            itemid.Enabled = true;            #endregion            #region 获取上传文件的信息            string md5Fisrt = GenerateCheckCode10();            string uidFisrt = "0";            string fileLengthFisrt = FileUpload1.PostedFile.ContentLength.ToString();            string fileSizeFisrt = Math.Round(Convert.ToDouble(FileUpload1.PostedFile.ContentLength) / Convert.ToDouble(1024 * 1024), 2).ToString() + "MB";            string pathLocalFisrt = FileUpload1.PostedFile.FileName;            xdb_files model = db.GetModelByID(id);            md5Fisrt = model.FileMD5;            string FileType = FileUpload1.FileName.Substring(FileUpload1.FileName.LastIndexOf(".") + 1);            if (FileUpload1.FileName == "" || Request.Files.Count < 0)            {                string msg = "请选择文件!";                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");            }            else if (pathLocalFisrt != model.FilePathLocal || fileLengthFisrt != Convert.ToString(model.FileLength))            {                string msg = "第一次上传文件与本次上传文件不符合!";                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");            }                         else if (FileType.ToLower() != "rar")            {                string msg = "文件格式不正确!";                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");            }            else             {                #region 更新上传进度                int num = 0;                string struid = uidFisrt;                string strfid = id.ToString();                string strFileSize = fileLengthFisrt;                string strRangePos = num.ToString();                if (strFileSize.Length > 0                    && struid.Length > 0                    && strfid.Length > 0                    && md5Fisrt.Length > 0                    && strRangePos.Length > 0                    && Request.Files.Count > 0)                {                    long fileSize = Convert.ToInt64(strFileSize);                    long rangePos = Convert.ToInt64(strRangePos);                    int uid = Convert.ToInt32(struid);                    int fid = Convert.ToInt32(strfid);                    //临时文件大小                    HttpPostedFile file = Request.Files.Get(0);                    long rangeSize = 131072;                    long rangeSiHH = 131072;                    xdb_files infModel = new xdb_files();                    for (long i = model.FilePos; i <= Convert.ToInt32(file.InputStream.Length); )                    {                        if (db.GetFileInfByFid(fid, ref infModel))                        {                            //已上传大小 = 文件块索引 + 临时文件块大小                            //long postedLength = rangePos + rangeSize;                            long postedLength = i + rangeSize;                            long nownum = i;                            if (file.InputStream.Length < postedLength)                            {                                postedLength = file.InputStream.Length - nownum;                                rangeSiHH = file.InputStream.Length - nownum;                            }                            //上传百分比 = 已上传大小 / 文件总大小                            double per = ((double)postedLength / (double)fileSize) * 100;                            decimal perd = Math.Round((decimal)per, 2);                            string postedPercent = perd.ToString() + "%";                            //保存文件块数据                            FileResumer res = new FileResumer();                            res.m_FileSize = fileSize;//根据客户端文件大小在服务端创建文件                            res.RangePos = rangePos;                            #region                            m_writeLock.AcquireWriterLock(1000);                            //文件不存在则创建                            if (!File.Exists(infModel.FilePathRemote))                            {                                FileStream fs = File.OpenWrite(infModel.FilePathRemote);                                BinaryWriter w = new BinaryWriter(fs);                                for (long ii = 0; ii < infModel.FileLength; ++ii)                                {                                    w.Write((byte)0);                                }                                w.Close();                                fs.Close();                            }                            m_writeLock.ReleaseWriterLock();                            //上传的文件大小不为空                            if (rangeSiHH > 0)                            {                                //文件已存在,写入数据                                //可能会有多个线程同时写文件。                                FileStream fs = new FileStream(infModel.FilePathRemote, FileMode.Open, FileAccess.Write, FileShare.Write);                                fs.Seek(i, SeekOrigin.Begin);                                byte[] ByteArray = new byte[rangeSiHH];                                file.InputStream.Read(ByteArray, 0, (int)rangeSiHH);                                fs.Write(ByteArray, 0, (int)rangeSiHH);                                fs.Flush();                                fs.Close();                            }                            #endregion                            //更新文件进度                            db.UpdateProgress(uid, fid, rangePos, postedLength, postedPercent);                            i += rangeSize;                        }                    }                }                #endregion                #region 上传完成                db.UploadComplete(md5Fisrt);                #endregion                GetList();            }            #endregion            EnabledStop();        }        /// <summary>        ///  停止        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected void lbClose_Click(object sender, CommandEventArgs e)        {            EnabledStop();        }        /// <summary>        /// 删除        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected void lbDel_Click(object sender, CommandEventArgs e)        {            int id = Convert.ToInt32(e.CommandArgument);            HttpUploaderDB db = new HttpUploaderDB();            db.Del(id);            GetList();        }        /// <summary>        /// 批量删除事件        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected void btnAllDelete_Command(object sender, CommandEventArgs e)        {            HttpUploaderDB db = new HttpUploaderDB();            string ids = Request.Form["Item"];            switch (e.CommandName)            {                case "delete":                    BakDelete(ids);                    break;            }            GetList();        }        /// <summary>        /// 批量删除方法        /// </summary>        /// <param name="ids"></param>        private void BakDelete(string ids)        {            HttpUploaderDB db = new HttpUploaderDB();            string strapp = ids;            string[] strtemp = strapp.Split(',');            foreach (string strs in strtemp)            {                db.Del(Convert.ToInt32(strs.ToString()));            }        }          /// <summary>        /// 获取数据列表        /// </summary>        public void GetList()        {            HttpUploaderDB db = new HttpUploaderDB();            rptList.DataSource = db.GetList();            rptList.DataBind();            EnabledStop();        }        /// <summary>        /// 禁用所有停止控件,启用所有续传控件        /// </summary>        public void EnabledStop()        {            foreach (RepeaterItem grv in rptList.Items)            {                LinkButton lb1 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbTop");//续传                LinkButton lb2 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbClose");//停止                HiddenField hidk = (HiddenField)rptList.Items[grv.ItemIndex].FindControl("hidOK");//上传是否完成                if (hidk.Value.ToLower() == "true")                {                    lb1.Enabled = false;                    lb2.Enabled = false;                }                else                {                    lb1.Enabled = true;                    lb2.Enabled = false;                }            }        }        /// <summary>        /// 刷新时间        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected void Timer1_Tick(object sender, EventArgs e)        {            Label1.Text = DateTime.Now.ToString();            //GetList();        }        private string GenerateCheckCode10()        {            int number;            char code;            string checkCode = String.Empty;            System.Random random = new Random();            for (int i = 0; i < 10; i++)            {                number = random.Next();                if (number % 2 == 0)                    code = (char)('0' + (char)(number % 10));                else                    code = (char)('A' + (char)(number % 26));                checkCode += code.ToString();            }            return checkCode;        }    }}