在做項目時候,一些表單要求有圖片上傳功能,今天總結一下在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();
}
功能實現!