WebAPI 多文件批量上傳,大文件上傳,實現先驗證文件再存磁盤

研究了幾天的 WebAPI 多文件批量上傳功能,也終於找到了無法先驗證再存盤的解決方法,以下是本次的測試代碼,希望能對大家有幫助!~


  • 首先上服務端多文件接收的接口代碼

    public class FileController : ServiceBase
    {
        ///
        /// 服務端文件上傳接口
        ///
        [Route("~/upload")]
        [HttpPost, HttpGet]
        public async Task<string> Upload()
        {
            System.Diagnostics.Debugger.Launch(); //喚起調試器

            if (!Request.Content.IsMimeMultipartContent())
                return "缺少附件。";

            var savePath = $@"D:\ReceiveUpload\{DateTime.Now.ToString("yyyy-MM-dd")}";    //定義一個用於存儲接收文件的目錄

            //確保目錄存在
            if (!Directory.Exists(savePath))
                Directory.CreateDirectory(savePath);

            //使用異步接收客戶端上傳的多個文件信息
            var multi = await Request.Content.ReadAsMultipartAsync();
            var fileCount = 0;

            //遍歷全部文件
            foreach (var content in multi.Contents)
            {
                var contentType = content.Headers.ContentType;                            //客戶端定義的Content-Type
                var name = content.Headers.ContentDisposition.Name;                       //客戶端定義的Name參數
                var fileName = content.Headers.ContentDisposition.FileName?.Trim('"');    //客戶端上傳的文件名稱
                var fileType = Path.GetExtension(fileName)?.TrimStart('.');               //獲取文件擴展名
                
                if (string.IsNullOrWhiteSpace(fileName))
                    continue;//非文件則跳過

                ++fileCount;

                //獲取文件流數據(根據自己需求2選1即可)
                var fileBytes = await content.ReadAsByteArrayAsync();
                var fileStream = await content.ReadAsStreamAsync();

                var fileLength = fileStream.Length;             //獲取文件大小

                switch (fileType.ToLower())
                {
                    case "jpg":
                    case "png":
                        #region 驗證圖片文件
                        {
                            var image = new Bitmap(fileStream); //獲取圖片信息
                            var imgWidth = image.Width;         //獲取圖片寬度
                            var imgHeight = image.Height;       //獲取圖片高度
                            var imgLength = fileStream.Length;  //獲取圖片大小

                            //PS:可在此處對圖片大小與分辨率大小進行驗證

                            //將此圖片保存到磁盤
                            image.Save($@"{savePath}\{fileName}");
                            //釋放資源
                            image.Dispose();
                        }
                        #endregion
                        break;
                    default:
                        //return $"不允許的文件格式“{fileType}”。";
                        
                        //將文件保存到磁盤中
                        File.WriteAllBytes($@"{savePath}\{fileName}", fileBytes);
                        break;
                }

                //釋放資源
                fileStream.Dispose();
            }

            return $"已接收到{fileCount}個文件。";
        }
    }
  • 其次是客戶端程序的文件上傳代碼

        /// <summary>
        /// 客戶端批量上傳文件
        /// </summary>
        [TestMethod]
        public void TestUpload()
        {
            var url = "http://127.0.0.1:8080/upload";
            var filesPath = new List<string>();
            {
                filesPath.Add(@"D:\測試文件\17,443KB (9088x3776).jpg");
                filesPath.Add(@"D:\測試文件\829KB.7z");
                filesPath.Add(@"D:\測試文件\107MB.zip");
                filesPath.Add(@"D:\測試文件\812MB.rar");
            }
            using (var client = new System.Net.Http.HttpClient())
            using (var content = new System.Net.Http.MultipartFormDataContent())
            {
                foreach (string filePath in filesPath)
                #region 添加文件
                {
                    var fileName = filePath.Substring(filePath.LastIndexOf('\\') + 1);
                    var fileBytes = File.ReadAllBytes(filePath);

                    var fileContent = new System.Net.Http.ByteArrayContent(fileBytes);
                    {
                        //定義內容標頭,使用 attachment 附件上傳模式
                        fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
                        {
                            //定義一個Name參數 (非必填項,根據個人需求即可)
                            Name = $"文件{++i}",
                            //告訴服務端當前文件的名稱
                            FileName = fileName
                        };
                    }
                    content.Add(fileContent);
                }
                #endregion

                var responseMessage = client.PostAsync(url, content).Result;
                var status = responseMessage.StatusCode;
                var result = responseMessage.Content.ReadAsStringAsync().Result; //返回的頁面內容

                //測試結果返回:"已接收到4個文件。"
            }
        }

  • 以上,如出現 Request 內容超過限制的長度異常,注意配置 Web.config

  <!--修改限制Request數據大小(單位:KB)-->
  <system.web>
    <httpRuntime targetFramework="4.6.1" maxRequestLength="4194304"/>
  </system.web>

  <!--修改限制Request數據大小(單位:Byte)-->
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="4294967295" />
      </requestFiltering>
    </security>
  </system.webServer>
  • 若上一步配置後還沒能解決的,可再嘗試修改 App_Start/WebApiConfig.cs

此處是在 https://www.cnblogs.com/dopeter/p/4675174.html 這篇文章中看到的,因實際測試時已通過上一步的配置 Web.config 已解決,所以還沒能用上這段 ~ :-)

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // 重寫上傳文件的內容存入內存的動作,爲解決無法通過流上傳大文件問題
            GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Hosting.IHostBufferPolicySelector), new NoBufferPolicySelector());
        }
    }

    /// <summary>
    /// 重寫上傳文件的內容存入內存的動作,爲解決無法通過流上傳大文件問題
    /// </summary>
    public class NoBufferPolicySelector : System.Web.Http.WebHost.WebHostBufferPolicySelector
    {
        public override bool UseBufferedInputStream(object hostContext)
        {
            var context = hostContext as System.Web.HttpContextBase;

            if (context != null)
            {
                if (context.Request.HttpMethod == System.Net.Http.HttpMethod.Post.ToString() && context.Request.ContentLength > 200000)
                    return false;
            }

            return true;
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章