net core WebApi——文件分片下載

[toc]html

前言

上一篇net core WebApi——文件分片上傳與跨域請求處理介紹完文件的上傳操做,原本是打算緊接着寫文件下載,中間讓形形色色的事給耽誤的,今天仍是抽個空整理完文件這塊兒,而後就能夠鼓搗別的東西了。前端

開始

這裏咱們仍然使用基礎工程,須要下載的朋友請移步net core Webapi 總目錄,代碼都是與博客的進度基本同步的。 上傳的時候咱們介紹過度片的思路,而下載也同樣,只是客戶端與服務端角色轉換下就行了。 後端linux

  1. 接收前端下載請求,校驗請求信息,返回文件基本信息
  2. 根據前端請求文件片斷進行下載流處理。

前端後端

  1. 向後端發起下載請求,獲取文件總片斷數
  2. 根據片斷數循環請求文件片斷流進行下載(可單獨請求某一片斷文件數據)

文件下載相對於上傳來講稍微簡潔點兒,若是不考慮服務器壓力也能夠一個a標籤解決下載問題,分片的意義就在於每次與服務端的交互減小流量,有些時候咱們推薦拿空間換時間,但對於大流量來講仍是慢慢來比較好,單次訪問量若是大再加上多併發怕是服務器會受不了,因此有了一片片分步來循環訪問這個方法。api

也是直接來看代碼吧,咱們在FileController建立幾個接口方法RequestDownloadFileFileDownload跨域

/// <summary>
        /// 請求下載文件
        /// </summary>
        /// <param name="fileInfo">文件參數信息[name]</param>
        /// <returns></returns>
        [HttpPost, Route("RequestDownload")]
        public MessageEntity RequestDownloadFile([FromBody]Dictionary<string, object> fileInfo)
        {

        }

        /// <summary>
        /// 分段下載文件
        /// </summary>
        /// <param name="fileInfo">請求參數信息[index,name]</param>
        /// <returns></returns>
        [HttpPost, Route("Download")]
        public async Task<IActionResult> FileDownload([FromBody]Dictionary<string, object> fileInfo)
        {

        }

RequestDownloadFile服務器

這裏說明下,與服務端的操做都要儘量多的確認身份信息(固然後續會有說這塊兒),文件的相關操做也同樣須要而且還要嚴格點兒,我這裏就是爲了作示例演示因此只傳文件信息便可。併發

public MessageEntity RequestDownloadFile([FromBody]Dictionary<string, object> fileInfo)
        {
            MessageEntity message = new MessageEntity();
            string fileName = string.Empty;
            string fileExt = string.Empty;
            if (fileInfo.ContainsKey("name"))
            {
                fileName = fileInfo["name"].ToString();
            }
            if (fileInfo.ContainsKey("ext"))
            {
                fileExt = fileInfo["ext"].ToString();
            }
            if (string.IsNullOrEmpty(fileName))
            {
                message.Code = -1;
                message.Msg = "文件名不能爲空";
                return message;
            }
            //獲取對應目錄下文件,若是有,獲取文件開始準備分段下載
            string filePath = $".{AprilConfig.FilePath}{DateTime.Now.ToString("yyyy-MM-dd")}/{fileName}";
            filePath = $"{filePath}{fileExt}";
            FileStream fs = null;
            try
            {
                if (!System.IO.File.Exists(filePath))
                {
                    //文件爲空
                    message.Code = -1;
                    message.Msg = "文件還沒有處理完";
                    return message;
                }
                fs = new FileStream(filePath, FileMode.Open);
                if (fs.Length <= 0)
                {
                    //文件爲空
                    message.Code = -1;
                    message.Msg = "文件還沒有處理完";
                    return message;
                }
                int shardSize = 1 * 1024 * 1024;//一次1M
                RequestFileUploadEntity request = new RequestFileUploadEntity();
                request.fileext = fileExt;
                request.size = fs.Length;
                request.count = (int)(fs.Length / shardSize);
                if ((fs.Length % shardSize) > 0)
                {
                    request.count += 1;
                }
                request.filedata = GetCryptoString(fs);

                message.Data = request;
            }
            catch (Exception ex)
            {
                LogUtil.Debug($"讀取文件信息失敗:{filePath},錯誤信息:{ex.Message}");
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }

            return message;
        }

FileDownloadapp

public async Task<IActionResult> FileDownload([FromBody]Dictionary<string, object> fileInfo)
        {
            //開始根據片斷來下載
            int index = 0;
            if (fileInfo.ContainsKey("index"))
            {
                int.TryParse(fileInfo["index"].ToString(), out index);
            }
            else
            {
                return Ok(new { code = -1, msg = "缺乏參數" });
            }
            string fileName = string.Empty;
            string fileExt = string.Empty;
            if (fileInfo.ContainsKey("name"))
            {
                fileName = fileInfo["name"].ToString();
            }
            if (fileInfo.ContainsKey("ext"))
            {
                fileExt = fileInfo["ext"].ToString();
            }
            if (string.IsNullOrEmpty(fileName))
            {
                return Ok(new { code = -1, msg = "文件名不能爲空" });
            }
            //獲取對應目錄下文件,若是有,獲取文件開始準備分段下載
            string filePath = $".{AprilConfig.FilePath}{DateTime.Now.ToString("yyyy-MM-dd")}/{fileName}";
            filePath = $"{filePath}{fileExt}";
            if (!System.IO.File.Exists(filePath))
            {
                return Ok(new { code = -1, msg = "文件還沒有處理" });
            }
            using (var fs = new FileStream(filePath, FileMode.Open))
            {
                if (fs.Length <= 0)
                {
                    return Ok(new { code = -1, msg = "文件還沒有處理" });
                }
                int shardSize = 1 * 1024 * 1024;//一次1M
                int count = (int)(fs.Length / shardSize);
                if ((fs.Length % shardSize) > 0)
                {
                    count += 1;
                }
                if (index > count - 1)
                {
                    return Ok(new { code = -1, msg = "無效的下標" });
                }
                fs.Seek(index * shardSize, SeekOrigin.Begin);
                if (index == count - 1)
                {
                    //最後一片 = 總長 - (每次片斷大小 * 已下載片斷個數)
                    shardSize = (int)(fs.Length - (shardSize * index));
                }
                byte[] datas = new byte[shardSize];
                await fs.ReadAsync(datas, 0, datas.Length);
                //fs.Close();
                return File(datas, "application/x-gzip");
            }
        }

看過上傳的朋友都清楚上傳是三步,請求上傳=>開始上傳=>合併,而下載只須要兩步,由於合併與否其實不那麼重要了,反正文件流都給客戶端了,那邊本身判斷須要從新下載仍是下載部分片斷都是他們本身的事了(服務端只管賣,東西有問題本身解決,多理想的狀態)。async

測試

搞完以後從新生成,運行以後咱們來測試下效果,測試以前不要忘了接口白名單(作過登陸相關的驗證操做的忽略這點)。 測試

這裏提示error是由於解析錯誤,實際請求下載測試是正常的,若是有異常問題能夠與我聯繫。

小結

文件相關的上傳下載以及常規信息的操做能夠告一段落,至於下一步鼓搗點兒啥也還沒想好,原本還在看着linux相關的操做作發佈部署的鋪墊,看最近整體的進度吧,總之,學如逆水行舟,若是不想溺水,就握好你的漿(固然有些人不用漿那就算了,告辭)。

相關文章
相關標籤/搜索