net core 断点上传

一、前言

    关于这边文章,一直都想写上去来做记录,终于今晚是看了《我想我们在一起》这电影之后,触动而写。 有些事情还是不要等待,能当下做就赶紧做,不然都是给自己遗憾的。 回归正题,说的是断点上传,需要把文件切割成片。下面是我个人的大概思路,也借鉴了百度一些前辈们留下的经验而成(说借鉴其实差不多就是ctrl+c  和ctrl+v 的问题)。

二、前端代码

    只是提供一个分片思路。 个人感觉下面js 代码标红部分是比较重要的吧。

 <input class="easyui-filebox" name="filevideo" id="filevideo" labelPosition="top" data-options="prompt:'请选择视频',buttonText:'选择',accept:'video/avi,audio/mp4, video/mp4,video/mpeg,video/avi'">

 

       

var bytesPerPiece = 1024*1024 ; // 每个文件切片大小定为1MB . var totalPieces; //发送请求 window.uploads = function (obj) { var blob =$("#filevideo").filebox("files")[0];//1.获取文件对象 var start = 0; var end; var index = 0;//索引片数 var filesize = blob.size;//2.文件大小 var filename = blob.name;//3.文件名称带后缀名 if (filename.indexOf(".mp4") == -1) { $.messager.alert('提示', '目前只支持上传mp4格式'); return; }
//计算文件切片总数 totalPieces = Math.ceil(filesize / bytesPerPiece); //4.计算分片总数 var guid= '@Guid.NewGuid().ToString()';//这是我自定义的,以GUID 命名一个临时文件夹
        //5.开始分片
while (start < filesize) { end = start + bytesPerPiece; if (end > filesize) { end = filesize; } var chunk = blob.slice(start, end);//6.切割文件 var formData = new FormData();//7.用FormData 附带参数 上传文件 formData.append("file", chunk, filename); formData.append("fileName", fid); formData.append("totalPieces", totalPieces); formData.append("currentPieces", index + 1); formData.append("guid", guid); $.ajax({ url: '@Url.Content("~/Admins/Video/UploadFile")', type: 'POST', cache: false,//这个很重要 data: formData, processData: false,//这个很重要 contentType: false, dataType:'json', }).done(function (result) {             
            
            //这一句防止重复调用
if (proceseBarVal == 100) { return; } if (result.isuccess)//是否上传成功 { if (servercurent.currentPieces != -1) { //这里是计算当前进度 } else { //完成上传 //执行合并接口 $.ajax({ url: '@Url.Content("~/Admins/Video/MeterFile")', type: 'POST', cache: false, data: data, dataType: "json", success: function (res) { if (res.success) { } else { $.messager.alert("提示", res.msg) } } }); } } }).fail(function (res) { }); start = end; index++; } }

 

 

 

三、后端代码

     看这代码还是有点混乱的,没有做整理。 后续附加一个demo出来比较好。

/// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="fileName">临时文件夹名称</param>
        /// <param name="totalPieces"></param>
        /// <param name="currentPieces"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> UploadFile(string fileName, string totalPieces, string currentPieces,string guid)
        {
            ResultData rmodel = new ResultData();
            string ID = Guid.NewGuid().ToString();
            try
            {
                var filebase = Request.Form.Files;
                string webRootPath = _hostingEnvironment.WebRootPath;
                string virRoot = "/files/video/temp/" + UserName+ "/" + DateTime.Now.ToString("yyyyMMdd") + "/" + guid + "/";//虚拟路径,用于存数据库
                if (!Directory.Exists(webRootPath + virRoot))
                    Directory.CreateDirectory(webRootPath + virRoot);
                if (filebase.Count > 0)
                {
                    for (int i = 0; i < filebase.Count; i++)
                    {
                        var file = filebase[i];

                        virRoot = virRoot + currentPieces;

                        var filePath = webRootPath + virRoot;

                        using (var stream = new FileStream(filePath, FileMode.Create))
                        {
                            await file.CopyToAsync(stream).ConfigureAwait(false);
                        }


                        if (totalPieces == currentPieces)
                        {
                            string extName = FileHelper.GetFileExtendName(filebase[i].FileName);
                            //上传完毕之后,就直接合并! 
                            rmodel.data = new
                            {
                                dir = webRootPath + "/files/video/temp/" + UserName + "/" + DateTime.Now.ToString("yyyyMMdd") + "/" + guid + "/",
                                exName = Guid.NewGuid().ToString() + extName,
                                currentPieces = -1 //MeterFile(webRootPath + "/files/video/temp/" + UserName + "/" + DateTime.Now.ToString("yyyyMMdd") + "/" + guid+ "/", Guid.NewGuid().ToString() + extName),
                            };
                            rmodel.isuccess = true;
                            rmodel.msg = "上传成功!";
                        }
                        else
                        {
                            rmodel.isuccess = true;
                            rmodel.data = new
                            {
                                currentPieces = currentPieces
                            };
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                rmodel.msg = ex.Message;
            }

            return rmodel.ToJson();
        }


        /// <summary>
        /// 合并文件
        /// </summary>
        [HttpPost]
        public AjaxResult MeterFile(string dir, string exName)
        {
            AjaxResult result = new AjaxResult() {  Success=false};
            try
            {
                var files = System.IO.Directory.GetFiles(dir);//获得下面的所有文件  
                string localhost = dir.Replace("temp/" + UserName + "/", "");
                if (!Directory.Exists(localhost))
                    Directory.CreateDirectory(localhost);
                var fs = new FileStream(localhost + exName, FileMode.Create);

                foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N Write
                {
                    var bytes = System.IO.File.ReadAllBytes(part);
                    fs.Write(bytes, 0, bytes.Length);
                    bytes = null;
                    System.IO.File.Delete(part);//删除分块
                }
                fs.Close();
                //System.IO.Directory.Delete(dir);//删除文件夹 
                result.Msg = "上传成功";
                result.Success = true;
                result.Data = new
                {
                    url = Path.Combine(dir.Replace(_hostingEnvironment.WebRootPath, "").Replace("temp/" + UserName + "/", ""), exName)
                };
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog_LocalTxt(ex.Message);
                result.Msg = "合并失败,请联系管理员!";
            }
            
            return result;
        }

 

四、结束

   在此代码之前,我是直接把文件切片上传之后,马上合并,导致一个问题就是,文件没有上传完成马上执行合并方法,1.删除文件夹报错  2.合并的视频无法播放或者播放不全。 后来跟同事讨论了一下,把文件上传完成之后,再请求合并接口(注意,必须要设置同步,异步的话会出现文件未上传完成就进行合并了)。我上面只是提供一个上传文件思路,并不是最优的代码。所以进行优化。 

posted @ 2021-07-16 19:14  linxChou  阅读(126)  评论(0编辑  收藏  举报