Asp.Net Core 輕鬆學-一行代碼搞定文件上傳

前言

    在 Web 應用程序開發過程當中,老是沒法避免涉及到文件上傳,此次咱們來聊一聊怎麼去實現一個簡單方即可複用文件上傳功能;經過建立自定義綁定模型來實現文件上傳。git

1. 實現自定義綁定模型
  • 1.1 在 Asp.Net Core MVC 中,內置了不少種綁定模型,讓咱們能夠很方便的去使用,好比下面經常使用的幾種綁定模型
FromBodyAttribute
 FromFromAttribute
 FromQueryAttribute
 FromHeaderAttribute
 FromServicesAttribute
 FromRouteAttribute
  • 常見用法好比
[HttpPost]
     public async Task<IActionResult> PostInfo([FromBody]UserInfo user,[FromQuery] string city)
    {
        ...
    }
    1. 查看以上綁定模型,惟獨缺乏一個 FromFileAttribute ,下面就來實現一個本身的 FromFileAttribute
public class FromFileAttribute : Attribute, IBindingSourceMetadata
    {
        public BindingSource BindingSource => BindingSource.FormFile;
    }
  • 很是簡單,就三行代碼,徹底照抄系統內置的綁定模型,惟一不一樣的就是指定 BindingSource 爲 BindingSource.FormFile。
2. 實現一個上傳文件實體類,專門用於接收客戶端參數
  • 2.1 建立 UserFile
public class UserFile
    {
        public string FileName { get; set; }
        public long Length { get; set; }
        public string Extension { get; set; }
        public string FileType { get; set; }

        private readonly static string[] Filters = { ".jpg", ".png", ".bmp" };
        public bool IsValid => !string.IsNullOrEmpty(this.Extension) && Filters.Contains(this.Extension);

        private IFormFile file;
        public IFormFile File
        {
            get { return file; }
            set
            {
                if (value != null)
                {
                    this.file = value;

                    this.FileType = this.file.ContentType;
                    this.Length = this.file.Length;
                    this.Extension = this.file.FileName.Substring(file.FileName.LastIndexOf('.'));
                    if (string.IsNullOrEmpty(this.FileName))
                        this.FileName = this.file.FileName;
                }
            }
        }

        public async Task<string> SaveAs(string destinationDir = null)
        {
            if (this.file == null)
                throw new ArgumentNullException("沒有須要保存的文件");

            if (destinationDir != null)
                Directory.CreateDirectory(destinationDir);

            var newName = DateTime.Now.Ticks;
            var newFile = Path.Combine(destinationDir ?? "", $"{newName}{this.Extension}");
            using (FileStream fs = new FileStream(newFile, FileMode.CreateNew))
            {
                await this.file.CopyToAsync(fs);
                fs.Flush();
            }

            return newFile;
        }
    }
  • UserFile 是一個帶保持文件行爲的實體類,該類的公共屬性用於從表單域中接收和屬性名稱相同的表單值,其中公共屬性 File 用於接收文件,並在設置值的時候去作一些其它屬性初始化的工做,好比文件長度和擴展名、文件類型
  • 其中還實現了一個簡單的文件過濾器,判斷客戶端上傳的文件是否屬於服務端容許上傳的文件擴展名
  • 最後 SaveAs(string destinationDir = null) 經過傳入指定目錄,將文件保存,並返回保存後的文件絕對路徑
3. 上傳文件
  • 3.1 下面就定義一個簡單的 API 接口,用於測試上傳文件
[HttpPost]
        public async Task<IActionResult> Post([FromFile]UserFile file)
        {
            if (file == null || !file.IsValid)
                return new JsonResult(new { code = 500, message = "不容許上傳的文件類型" });

            string newFile = string.Empty;
            if (file != null)
                newFile = await file.SaveAs("/data/files/images");

            return new JsonResult(new { code = 0, message = "成功", url = newFile });
        }
  • 3.2 首先是在 Post([FromFile]UserFile file) 中使用上面建立的 FromFileAttribute 對模型 UserFile 進行綁定,而後驗證文件是否正確,接下來經過 file.SaveAs("/data/files/images"); 保存文件github

  • 3.3 上傳代碼很是簡單,幾乎到了沒法精簡的程度,最終發揮做用的就是 file.SaveAs 操做async

4. 上傳測試
  • 4.1 如今經過控制檯啓動服務

  • 4.2 使用 Postman 模擬表單上傳文件

  • 4.3 上傳成功,如今來查看目錄下是否有文件

結語
  • 在上傳表單中,咱們定義了附件的名稱爲 file 對應綁定模型的公共屬性 File,這樣模型就能夠自動得到該文件
  • 表單中還傳遞了另一個字段 filename,對應綁定模型的公共屬性 FileName,實現自定義文件友好顯示名稱
  • 經過自定義模型綁定,實現了快速上傳文件功能,該功能只能用於上傳小文件,對於大文件,仍是須要實現分片上傳,或者使用 CDN 等服務商的接口
示例代碼下載

(經 海闊天空XM. 提醒,因爲上傳了編譯後的 dll 引發部分朋友殺毒軟件誤報,現已從新上傳,感謝!)測試

https://github.com/lianggx/EasyAspNetCoreDemo/tree/master/Ron.UploadFilethis

相關文章
相關標籤/搜索