在做项目时候,一些表单要求有图片上传功能,今天总结一下在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="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();
}
功能实现!