html前端使用JS分片上传大文件到服务器,后端使用C#ASP.net接收前端传输的文件

前端使用js分片上传大文件代码

//注,js脚本可写在一个js文件里面,这样显得代码看起来简洁
  <script>
        var BYTES_PER_CHUNK = 1024 * 1024;//计算每个文件切割的大小-->1M
        var slices;//切割文件的总数
        var totalslices;//切割文件的总数
        var xhr;//待赋值XMLHttpRequest对象
        var start = 0;
        var end;
        var index = 0;
        var blob;
        var tagfilename;
        var oloaded = 0;
        function sendRequest() {
            blob = document.getElementById("file").files[0];//获取第一个文件对象
            start = 0;//切割文件的起始大小
            end;//切割文件的结束大小
            index = 0;
            tagfilename = "";
            ot = new Date().getTime();   //设置上传开始时间
            oloaded = 0;//设置上传开始时,以上传的文件大小为0
            slices = Math.ceil(blob.size / BYTES_PER_CHUNK);//
            totalslices = slices;
            end = start + BYTES_PER_CHUNK;
             if (end > blob.size) {
                end = blob.size;
            }
            uploadFile(blob, index, start, end);
        };
        function uploadFile(blob, index, start, end) {
            var fd;
            var chunk;
            var sliceindex = blob.name + "@@" + index;
            chunk = blob.slice(start, end);//切割文件,切割文件范围为start-end
            fd = new FormData();//表单形式的格式化
            /*****上传参数************/
            fd.append("UpgradeFileName", chunk, sliceindex);//服务器存储的文件名
            fd.append("totalslices", slices);//分割文件的总个数
            fd.append("totalsize", blob.size);//文件总的大小
            fd.append("tagfilename", tagfilename);
            fd.append("filesindex", index + 1);
            /*****上传参数************/
            xhr = new XMLHttpRequest();//新建XMLhttpRequest对象
            xhr.open("POST", "Handler1.ashx?action=uploadfile", true);//异步上传,同步上传会阻塞UI线程
            xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】,跨域时,则取消该方法即可
            xhr.onload = uploadCompete;//请求完成回调方法
            xhr.onerror = uploadFailed;//请求失败回调方法
            xhr.send(fd);//发送
        };
        //单个文件上传成功回调方法
        function uploadCompete(evt) {
            var data = eval('(' + evt.target.responseText + ')');//evt.target.responseText为json格式字符串,使用eval方法获取
            tagfilename = data.tagfilename;//回去上传到服务器文件的新的服务器存储的文件名
            console.log(data.tagfilename);//输出到控制台,供调试查看
            start = end;
            index++;//子文件上传成功,index加1,用于判断文件是否上传结束
            end = start + BYTES_PER_CHUNK;
            if (end > blob.size) {
                end = blob.size;
            }
            if (index < totalslices) {//当上传文件个数小于总个数时,继续上传下一个文件
                uploadFile(blob, index, start, end);
            }
             if (index >= totalslices) {
                 alert("文件上传成功");
                 var percentageDiv = document.getElementById("percentage");
                 percentageDiv.innerHTML = "100% 文件上传成功";
                }    
        };
        //单个文件上传失败的回调方法
        function uploadFailed(evt) {
           uploadFile(blob, index, start, end);
        };
         //取消上传
        function cancleUploadFile(){
            xhr.abort();
        };
         //上传进度实现方法,上传过程中会频繁调用该方法,在进行跨域上传时,需要配置远程服务器端和客户端界面,取消该方法则不会涉及到跨域问题。
        function progressFunction(evt) {
            var progressBar = document.getElementById("progressBar");
            var percentageDiv = document.getElementById("percentage");
            // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
            if (evt.lengthComputable) {
                progressBar.max = blob.size;
                progressBar.value = start + evt.loaded;
                if ((start + evt.loaded)/blob.size>=1)
                {
                    percentageDiv.innerHTML = "100% 请稍后,正在处理。。";
                }else
                {
                    percentageDiv.innerHTML = Math.round((start+evt.loaded) / blob.size * 100) + "%";
                }
                
            }
            var time = document.getElementById("time");
            var nt = new Date().getTime();//获取当前时间
            if (nt - ot >= 1000) {
            var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差,单位为s
                ot = new Date().getTime(); //重新赋值时间,用于下次计算
                var perload = start+ evt.loaded - oloaded; //计算该分段上传的文件大小,单位b
            oloaded = start+ evt.loaded;//重新赋值已上传文件大小,用以下次计算
            //上传速度计算
            var speed = perload/pertime;//单位b/s
            var bspeed = speed;
            var units = 'b/s';//单位名称
            if(speed/1024>1){
                speed = speed/1024;
                units = 'k/s';
            }
            if(speed/1024>1){
                speed = speed/1024;
                units = 'M/s';
            }
            speed = speed.toFixed(1);
            //剩余时间
            var resttime = ((blob.size-start-evt.loaded)/bspeed).toFixed(1);
                time.innerHTML = '文件上传速度:' + speed + units + ',剩余时间:' + resttime + 's';
                }
            if(bspeed==0) time.innerHTML = '上传已取消';
        };
    </script>
    
       <body>
    <form id="form1" runat="server">
        <div>
            <div class="page-header">
    <h1>上传文件
        <small>...</small>
    </h1>
    </div>
            <div class="content">
                <table >
                    <tbody>
                        <tr>
                            <th colspan="2"><input type="file" id="file" name="myfile"  style="font-size:20px ;width:30rem" class="btn btn-upload"/></th>
                            <th class="auto-style1"><input type="button" id="uploadfile" class="btn btn-upload" onclick="sendRequest()" value="上传" style="font-size:30px;margin-left:1rem;"/></th>
                        </tr>
                        <tr>
                            <th colspan="2" >         
                                <progress id="progressBar"  value="0" max="100" style="width:30rem;margin-top:1rem;"></progress>
                                <span id="percentage"></span></th>
                            <th class="auto-style1"><input type="button" id="btntest" onclick="cancleUploadFile()" class="btn btn-upload" value="取消" style="font-size:30px;margin-left:1rem;margin-top:1rem;"/></th>
                        </tr>
                        <tr>
                            <th colspan="3">
                               <span id="time" style="font-size:20px"></span>
                            </th>
                        </tr>
                    </tbody>
                </table>
            </div>
         
        </div>
    </form>
</body>

前端界面显示:
在这里插入图片描述

C# ASP.net后端文件处理代码

代码使用一般处理文件完成 Handler1.ashx
//注:文件合并没想出其他好方法,像浏览器下载的文件,都只生成一个,在一个文件上进行读写
 public void ProcessRequest(HttpContext context)
        {
            if(context.Request.QueryString["action"]!=null && context.Request.QueryString["action"].ToString()=="uploadfile")
            {
                string tagfilename = "";
                if(context.Request.Form["tagfilename"]==null || context.Request.Form["tagfilename"]=="")
                {
                    tagfilename = Guid.NewGuid().ToString();
                }
                else
                {
                    tagfilename = context.Request.Form["tagfilename"].ToString();
                }
                var file = context.Request.Files[0];
                int oldmin = file.FileName.LastIndexOf("\\");
                int oldmax = file.FileName.Length;
                string oldfilename="";
                if (oldmin<0)
                {
                    oldfilename = file.FileName;
                }
                else
                {
                    oldfilename = file.FileName.Substring(oldmin+2, oldmax - oldmin-2);
                }
                string newName = tagfilename + oldfilename;
                file.SaveAs(@"c:\files\" + newName);
                if(context.Request.Form["totalslices"] != null && context.Request.Form["filesindex"] != null && context.Request.Form["totalslices"] == context.Request.Form["filesindex"])
                {
                    int count = newName.LastIndexOf("@@");
                    int index =Convert.ToInt16(context.Request.Form["filesindex"]);
                    string eachname = newName.Substring(0, count);
                    string[] fileIn=new string[index];
                   for(int i=0;i<index;i++)
                    {
                        fileIn[i] = @"c:\files\" + eachname + "@@" + i.ToString();
                    }
                    fileCombine(fileIn, true, 1);
                }
                context.Response.Write("{\"success\":1,\"tagfilename\":\""+ tagfilename + "\"}");
            }
        }
          /// <summary>
        /// 文件合并函数,
        /// 可将任意个子文件合并为一个,为fileSplit()的逆过程
        /// delet标识是否删除原文件, change对data的首字节进行解密
        /// </summary>
        public void fileCombine(String[] fileIn, bool delet, int change)
        {
            //输入文件名校验
            if (fileIn == null || fileIn.Length == 0) return;
            string name = fileIn[0];
            int i1 = name.LastIndexOf("@@");//name.LastIndexOf('.');
            int i2 = name.Length;
            name = name.Substring(0, i1);                                   //剔除子文件拓展名".split"
            //string fileOut = (i1 == -1) ? name : name.Remove(i1, i2 - i1);  //剔除"@_1" -> "D:\\1.rar.split"                      
            //创建输出文件,已有则覆盖
            FileStream FileOut = new FileStream(name, FileMode.Create);

            for (int i = 0; i < fileIn.Length; i++)
            {
                //输入文件校验
                if (fileIn[i] == null || !System.IO.File.Exists(fileIn[i])) continue;
                //从子文件创建输入流
                FileStream FileIn = new FileStream(fileIn[i], FileMode.Open);
                byte[] data = new byte[1024];   //流读取,缓存空间
                int readLen = 0;                //每次实际读取的字节大小
                while ((readLen = FileIn.Read(data, 0, data.Length)) > 0)       //读取数据
                {
                    //输出,缓存数据写入文件
                    FileOut.Write(data, 0, readLen);
                    FileOut.Flush();
                }
                //关闭输入流,删除源文件
                FileIn.Close();
                if (delet) System.IO.File.Delete(fileIn[i]);
            }
            FileOut.Close();    //关闭输出流
        }

上传效果

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值