webUploader上傳組件 實際運用小結


WebUploader組件實際介紹:

  1. 官網:http://fex.baidu.com/webuploader/doc/index.html
  2. 組件優勢及優化總結:http://itindex.net/detail/49267-webuploader-%E6%96%87%E4%BB%B6-%E4%B8%8A%E4%BC%A0
  3. 組件暫停功能的問題:https://github.com/fex-team/webuploader/issues/488
  4. 斷點續傳問題:https://github.com/fex-team/webuploader/issues/142
  5. 具體思路可以先參考鏈接:http://www.sxrczx.com/pages/blog.kazaff.me/uxgb1423648892626.html

以下內容於你對上述組件有了大致了解的基礎上,結合C#實現大文件的上傳、斷點續傳、分塊等功能,展開說明的:

設計思路:在每次文件上傳前,獲取該文件的MD5值作為該文件的唯一標識符,然后對該文件進行分塊處理(此處每塊設置5M大小,詳見2),按塊分發請求(此處設置為3個線程發請求,詳見2)文件開始上傳前觸發,一個文件只會觸發一次 uploadStart事件,該事件會驗證之前該文件是否已上傳部分,返回已上傳部分的塊數編號列表,然后在下一個事件before-send(在文件分片處理之后,上傳之前會觸發)判斷哪些塊數已存在,上傳不存在的文件塊,至此基本上傳流程已完成。

    /// <summary>
    /// 文件上傳消息類
    /// </summary>
    public class UploaderResult
    {
        public UploaderResult()
        {
            this.IsOver = false;
            this.Chunk = 0;
            this.Chunks = 0;
            this.FileExtist = false;
            this.ChunkNum = new List<int>();
        }

        /// <summary>
        /// 文件名稱、當上傳完成時將返回最終的文件名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 文件是否全部上傳完成
        /// </summary>
        public bool IsOver { get; set; }

        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// 如果為分塊上傳、返回當前的分塊索引
        /// </summary>
        public int Chunk { get; set; }

        /// <summary>
        /// 總的分塊大小
        /// </summary>
        public int Chunks { get; set; }

        /// <summary>
        /// 文件的MD5碼
        /// </summary>
        public string Md5 { get; set; }

        /// <summary>
        /// 上傳的文件是否已經存在於服務器
        /// </summary>
        public bool FileExtist { get; set; }

        /// <summary>
        /// 服務器已經存在的區塊序號
        /// </summary>
        public List<int> ChunkNum { get; set; }

        /// <summary>
        /// 文件擴展名
        /// </summary>
        public string FileExtension { get; set; }

        /// <summary>
        /// 文件路徑
        /// </summary>
        public string FilePath { get; set; }

        /// <summary>
        /// 文件大小
        /// </summary>
        public int FileSize { get; set; }
    }
        /// <summary>
        /// 斷點續傳檢測、MD5檢測 秒傳亦可以在這個方法塊中實現,看需求
        /// </summary>
        public static UploaderResult ProcessCheck(HttpRequestBase request, string savepath = null
            , Func<HttpPostedFileBase, string> setfilename = null, Func<string, bool> md5check = null)
        {
            UploaderResult obj = new UploaderResult();
            string tempFilePath = savepath + "temp\\" + request["md5"] + "\\";
          
            //文件大小
            long size = request.Form["size"] == null ? 0 : Convert.ToInt64(request.Form["size"]);

            //文件分塊大小
            long chunksize = request.Form["chunksize"] == null ? 0 : Convert.ToInt64(request.Form["chunksize"]);

            //文件區塊總數
            int chunks = chunksize != 0 ? Convert.ToInt32(size / chunksize) : 1;
            int j = 0;
            for (int i = 0; i <= chunks; i++)
            {
                if (File.Exists(tempFilePath + i.ToString()))
                {
                    obj.ChunkNum.Add(i);//服務器已經存在的區塊編號
                    j++;
                }
            }
            obj.Message = string.Format("服務器已經存在區塊數量{0},總區塊數量{1},占比{2}%", j
                , chunks + 1, chunks != 0 && j != 0 ? Convert.ToDouble(Convert.ToDouble(j) / Convert.ToDouble(chunks)) * 100 : 0);
            return obj;
        }     
        /// <summary>
        /// 文件上傳、保存
        /// </summary>
        /// <param name="request"></param>
        /// <param name="savepath"></param>
        /// <returns></returns>
        public static UploaderResult UploadSingleProcess(HttpRequestBase request, string savepath = null)
        {
            UploaderResult obj = new UploaderResult();
            if (request.Files.Count == 0)
            {
                obj.Message = "請求中不包含文件流信息";
                return obj;
            }
            if (request["size"] == null)
            {
                obj.Message = "文件大小為空";
                return obj;
            }
            string tempFilePath = savepath + "temp\\" + request["md5"] + "\\";
            string saveFilePath = savepath + "files\\";
            if (!Directory.Exists(saveFilePath))
            {
                Directory.CreateDirectory(saveFilePath);
            }
            //判斷是否分片,若文件大小不足分片,則直接保存
            if (request.Form.AllKeys.Any(m => m == "chunk"))
            {
                //分片時創建臨時文件目錄
                if (!Directory.Exists(tempFilePath))    
                {
                    Directory.CreateDirectory(tempFilePath);
                }
                //取得chunk和chunks
                int chunk = Convert.ToInt32(request.Form["chunk"]);
                int chunks = Convert.ToInt32(request.Form["chunks"]);
                HttpPostedFileBase file = request.Files[0];
                //根據GUID創建用該GUID命名的臨時文件
                file.SaveAs(tempFilePath + chunk.ToString());
                //判斷是否所有的分塊都已經上傳完畢
                string[] fileArr = Directory.GetFiles(tempFilePath);
                if (fileArr.Length == chunks) {
                    obj.IsOver = true;
                }
            }
            else
            {
                request.Files[0].SaveAs(saveFilePath + request.Files[0].FileName);
                obj.IsOver = true;
            }
            return obj;
        }
        /// <summary>
        /// 文件塊合並
        /// </summary>
        /// <returns></returns>
        public ActionResult MergeFiles()
        {
            string ext = Request.Form["fileExt"];
            string fileName = Request.Form["fileName"];
            string chunkNum = Request.Form["chunkNum"];
            string md5 = Request.Form["md5"];
            string tempFilePath = this.RootFolder + "\\temp\\" + md5 + "\\";
            string saveFilePath = this.RootFolder + "\\files\\" + fileName;  
            string[] fileArr = Directory.GetFiles(tempFilePath);
            try
            {
                lock (tempFilePath)
                {
                    if (Convert.ToInt32(chunkNum) == fileArr.Length)
                    {
                        if (System.IO.File.Exists(saveFilePath))
                        {
                            System.IO.File.Delete(saveFilePath);
                        }
                        FileStream addStream = new FileStream(saveFilePath, FileMode.Append, FileAccess.Write);
                        BinaryWriter AddWriter = new BinaryWriter(addStream);
                        for (int i = 0; i < fileArr.Length; i++)
                        {
                            //以小文件所對應的文件名稱和打開模式來初始化FileStream文件流,起讀取分割作用
                            FileStream TempStream = new FileStream(tempFilePath+i, FileMode.Open);
                            //用FileStream文件流來初始化BinaryReader文件閱讀器,也起讀取分割文件作用
                            BinaryReader TempReader = new BinaryReader(TempStream);
                            //讀取分割文件中的數據,並生成合並后文件
                            AddWriter.Write(TempReader.ReadBytes((int)TempStream.Length));
                            //關閉BinaryReader文件閱讀器
                            TempReader.Close();
                            TempStream.Close();
                        }
                        AddWriter.Close();
                        addStream.Close();
                        AddWriter.Dispose();
                        addStream.Dispose();
                        Directory.Delete(tempFilePath, true);
                    }
                    //驗證文件的MD5,確定文件的完整性 前端文件MD5值與后端合並的文件MD5值不相等
                    //if (UploaderHelper.GetMD5HashFromFile(saveFilePath) == md5)
                    //{
                    //    int i = 1;
                    //}
                    return Json("{hasError:\"false\"}");
                }
            }
            catch (Exception ex)
            {
                return Json("{hasError:\"true\"}");
            }
        }

后台代碼,還需要整理優化,當然如果有問題,大家可以一塊學習談論。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM