1. 程式人生 > 實用技巧 >ASP.Net Core -- 檔案上傳

ASP.Net Core -- 檔案上傳

在做專案時候,一些表單要求有圖片上傳功能,今天總結一下在ASP.Net Core中如何實現圖片上傳功能。

實現功能:點選按鈕或者檔案選擇框,選擇圖片,在input框內顯示圖片名稱,點選儲存,將圖片上傳到images資料夾,同時對圖片名稱重新命名儲存到資料庫。

新建一個Student.cs:

public class Student
    {
        public int Id { get; set; }
        
        public string FirstName { get; set; }
        
        public string LastName { get; set; }
        
        public DateTime BirthDate { get; set; }
       
        public Gender Gender { get; set; }

        public string PhotoPath { get; set; }
}

然後新建一個StudentCreateViewModel.cs

public class StudentCreateViewModel
    {
        [Display(Name = "姓"),Required]
        public string FirstName { get; set; }
        [Display(Name = "名"),Required,MaxLength(10)]
        public string LastName { get; set; }
        [Display(Name = "出生日期"), Required]
        public DateTime BirthDate { get; set; }
        [Display(Name = "性別")]
        public Gender Gender { get; set; }
        [Display(Name ="圖片")]
        public IFormFile Photo { get; set; }
}

這裡邊和Student.cs的欄位一樣,只不過Student.cs類檔案的屬性不夠用,所以新建一個ViewModel

裡邊圖片的型別是:IFormFile,為什麼要用這個型別?現在對IFormFile進行反編譯,如下:

public interface IFormFile
    {
        //
        // 摘要:
        //     Gets the raw Content-Type header of the uploaded file.
        string ContentType
        {
            get;
        }
        //
        // 摘要:
        //     Gets the raw Content-Disposition header of the uploaded file.
        string ContentDisposition
        {
            get;
        }
        //
        // 摘要:
        //     Gets the header dictionary of the uploaded file.
        IHeaderDictionary Headers
        {
            get;
        }
        //
        // 摘要:
        //     Gets the file length in bytes.
        long Length
        {
            get;
        }
        //
        // 摘要:
        //     Gets the form field name from the Content-Disposition header.
        string Name
        {
            get;
        }
        //
        // 摘要:
        //     Gets the file name from the Content-Disposition header.
        string FileName
        {
            get;
        }

        //
        // 摘要:
        //     Opens the request stream for reading the uploaded file.
        Stream OpenReadStream();
        //
        // 摘要:
        //     Copies the contents of the uploaded file to the target stream.
        //
        // 引數:
        //   target:
        //     The stream to copy the file contents to.
        void CopyTo(Stream target);
        //
        // 摘要:
        //     Asynchronously copies the contents of the uploaded file to the target stream.
        //
        // 引數:
        //   target:
        //     The stream to copy the file contents to.
        //
        //   cancellationToken:
        Task CopyToAsync(Stream target, CancellationToken cancellationToken = default(CancellationToken));
    }

可以看到,裡邊有很多重要的內容,其實它就是一個型別檔案,比如可以讀取檔案,獲取檔名稱,型別,還可以將上傳檔案的內容複製到目標流等等...

然後新建檢視,編寫表單:

<form method="post" enctype="multipart/form-data">
    <div style="width:800px;margin:0 auto">
        <div class="form-group">
            <label asp-for="FirstName"></label>
            <input asp-for="FirstName" class="form-control" />
            <span asp-validation-for="FirstName"></span>
        </div>
        <div>
            <label asp-for="LastName"></label>
            <input asp-for="LastName" class="form-control" />
            <span asp-validation-for="LastName"></span>
        </div>
        <div>
            <label asp-for="BirthDate"></label>
            <input asp-for="BirthDate" type="date" class="form-control" />
            <span asp-validation-for="BirthDate"></span>
        </div>
        <div>
            <label asp-for="Gender"></label>
            <select asp-for="Gender" asp-items="Html.GetEnumSelectList<Gender>()" class="form-control">
            </select>
            <span asp-validation-for="Gender"></span>
        </div>
        <div>
            <label asp-for="Photo"></label>
            <div class="custom-file">
                <input asp-for="Photo" class="form-control custom-file-input" />
                <label class="custom-file-label">請選擇照片....</label>
            </div>
        </div>
        <br />
        <input type="submit" value="save" class="btn btn-primary" />
    </div>
</form>

編寫js程式碼,當選擇圖片後,獲取路徑,將圖片名稱顯示在標籤中,如下:

<script>
      $(document).ready(function () {
          $('.custom-file-input').on('change', function () {
              var fileName = $(this).val().split('\\').pop();
              $(this).next('.custom-file-label').html(fileName);
          })
      })
</script>

控制器中接收表單內容,判斷是否有圖片上傳,如果有,獲取圖片名稱,對名稱重新命名編碼,儲存並儲存到檔案:

首先要使用到HostingEnvironment這個服務物件,因為它可以獲取專案中的 絕對路徑和相對路徑,然後注入:

public readonly IRepository<Student> _repository;
        private readonly HostingEnvironment _hostingEnvironment;

        public HomeController(IRepository<Student> repository,HostingEnvironment hostingEnvironment)
        {
            _repository = repository;
            _hostingEnvironment = hostingEnvironment;
        }

然後實現:

public IActionResult Create(StudentCreateViewModel model)
        {
            if (ModelState.IsValid)
            {
                string uniqueFileName = null;

                if (model.Photo != null)
                {
                    //找到根目錄下的wwwroot資料夾下的images資料夾
                    string uploadesFolder = Path.Combine(_hostingEnvironment.WebRootPath, "images");

                    //對圖片名稱進行重新命名,防止重複
                    uniqueFileName = Guid.NewGuid().ToString() + "-" + model.Photo.FileName;

                    //將路徑和新的圖片名稱合併
                    string filePath = Path.Combine(uploadesFolder, uniqueFileName);

                    //將圖片複製到指定資料夾中
                    model.Photo.CopyTo(new FileStream(filePath, FileMode.Create));
                }

                var list = new Student
                {
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    BirthDate = model.BirthDate,
                    Gender = model.Gender,
                    PhotoPath= uniqueFileName
                };

                var newModel = _repository.Add(list);

                return RedirectToAction(nameof(Detail), new { id = newModel.Id });
            }
            return View();
        }

功能實現!