Core上传单个图片和多个图片 编辑图片
一、单个文件上传
类需要加一个字段为:类型为 IFormFile
[Display(Name = "头像")]
public IFormFile Photo{get;set;}
IFormFile类中属性以及方法
名称 | 内容 |
---|---|
ContentType | 获取上传文件的原始Content-Type标头 |
ContentDisposition | 获取上传文件的原始Content-Disposition标头 |
Length | 获取文件长度,以字节为单位 |
FileName | 从Content-Disposition标头中获取的文件名 |
Name | 从Content-Disposition标头中获取的字段名称 |
Headers | 获取上传文件的HTTP消息头的字典信息 |
OpenReadStream() | 打开请求流以读取上传的文件 |
CopyTo() | 将上传文件的内容复制粘贴到流 |
CopyToAsync() | 异步地将上传文件的内容复制粘贴到流 |
页面:表单元素应设置为enctype=“multipart/form-data”
@* 我们使用asp-for的TagHelper设置input的属性为Photo
Photo属性类型是IFormFile,所以在运行的时候ASP.NET Core会将该标签生成上传控件(input type=file)*@
<div class="form-group row">
<label asp-for="Photo" class="col-sm-2 col-form-label"> </label>
<div class="col-sm-10">
<div class="custom-file">
<input asp-for="Photo" multiple class="form-control custom-fileinput"/>
<label class="custom-file-label">请选择图片....</label>
</div>
</div>
</div>
@*以下JavaScript代码的作用是,可以在上传标签中显示选定的上传文件名称。*@
@section Scripts{
<script>
$(document).ready(function () {
$(".custom-file-input").on("change",function () {
var fileName = $(this)
.val()
.split("\\")
.pop();
$(this)
.next(".custom-file-label")
.html(fileName);
});
});
</script>
}
控制器:
[HttpPost]
public IActionResult Create(StudentCreateViewModel model)
{
//模型验证判断是否通过
if(ModelState.IsValid)
{
string uniqueFileName = null;
//判断图片是否存在
if(model.Photo!= null)
{
//必须将图片文件上传到wwwroot的images文件夹中
//而要获取wwwroot文件夹的路径,我们需要注入ASP.NET Core提供的WebHostEnvironment服务
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath,"images");
//为了确保文件名是唯一的,我们在文件名后附加一个新的GUID值和一个下划线
uniqueFileName = Guid.NewGuid().ToString() + "_" + model.Photo.FileName;
string filePath = Path.Combine(uploadsFolder,uniqueFileName);
//使用IFormFile接口提供的CopyTo()方法将文件复制到wwwroot/images文件夹
model.Photo.CopyTo(new FileStream(filePath,FileMode.Create));
}
//封装
Student newStudent = new Student
{
Name = model.Name,
Email = model.Email,
Major = model.Major,
// 将文件名保存在Student对象的PhotoPath属性中
//它将被保存到数据库Students的表中
PhotoPath = uniqueFileName
};
// 调用添加的接口
_studentRepository.Insert(newStudent);
return RedirectToAction("Details",new{id = newStudent.Id});
}
return View();
}
二、多个文件上传
页面:表单元素应设置为enctype=“multipart/form-data”
@* 我们使用asp-for的TagHelper设置input的属性为Photo
Photo属性类型是IFormFile,所以在运行的时候ASP.NET Core会将该标签生成上传控件(input type=file)*@
<div class="form-group row">
<label asp-for="ClassName" class="col-sm-2 col-form-label">年纪:</label>
<select asp-for="ClassName" asp-items="Html.GetEnumSelectList<ClassNameEnum>()"
class="form-control custom-select mr-sm-2">
<option value="">请选择</option>
</select>
<span asp-validation-for="ClassName" class="text-danger"></span>
</div>
@*当上传一个文件时显示文件名,当上传多个文件时则显示文件数量*@
@section Scripts{
<script>
$(document).ready(function () {
$(".custom-file-input").on("change",function () {
//console.log($(this));
var fileLabel = $(this).next(".custom-file-label");
var files = $(this)[0].files;
if (files.length > 1) {
fileLabel.html("靓仔已经选择了:" + files.length + " 个文件");
} else if (files.length == 1) {
fileLabel.html(files[0].name);
}
});
});
</script>
}
//类需要改为 List<IFormFile>类型
[Display(Name = "头像")]
public List<IFormFile> Photos { get; set; }
上传
[HttpPost]
public IActionResult Create(StudentCreateViewModel model)
{
if (ModelState.IsValid)
{
string uniqueFileName = null;
if (model.Photos != null && model.Photos.Count() > 0)
{
foreach (IFormFile photo in model.Photos)
{
//必须将图片文件上传到wwwroot的images/avatars文件夹中而要获取wwwroot文件夹的
//路径,我们需要注入ASP.NET Core提供的WebHost Environment 服务通过
//WebHostEnvironment服务获取wwwroot文件夹的路径
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "avatars");
//为了确保文件名是唯一的,我们在文件名后附加一个新的GUID值和一个下划线
uniqueFileName = Guid.NewGuid().ToString() + "_" + photo.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
//使用IFormFile接口提供的CopyTo()方法将文件复制到wwwroot/images/avatars文件夹
photo.CopyTo(new FileStream(filePath, FileMode.Create));
}
}
Student newStudent = new Student
{
Name = model.Name,
Email = model.Email,
Major = model.Major,
ClassName = model.ClassName,
// 将文件名保存在Student对象的PhotoPath属性中
//它将被保存到数据库Students的表中
PhotoPath = uniqueFileName,
};
_studentRepository.AddStudent(newStudent);
return RedirectToAction("Detail", new { id = newStudent.Id });
}
return View();
}
三.编辑用户
[HttpPost]
public IActionResult Edit(StudentEditViewModel model)
{
Student student = _studentRepository.GetStudentById(model.Id);
//判断页面验证是否通过
if (ModelState.IsValid)
{
student.ClassName = model.ClassName;
student.Email = model.Email;
student.Id = model.Id;
student.Major = model.Major;
student.Name = model.Name;
//判断是否修改了图片
if (!string.IsNullOrEmpty(model.ExistingPhotoPath))
{
//当文件存在的情况把旧的删除
if (model.ExistingPhotoPath != null)
{
string filePath = Path.Combine(_webHostEnvironment.WebRootPath, "images", "avatars", model.ExistingPhotoPath);
System.IO.File.Delete(filePath);
}
//我们将新的图片文件保存到wwwroot/images/avatars文件夹中,并且会更新
//Student对象中的PhotoPath属性,最终都会将它们保存到数据库中
//这里添加了一个私有方法 ProcessUploadedFile(),
student.PhotoPath = ProcessUploadedFile(model);
}
Student updatedstudent = _studentRepository.Update(student);
return RedirectToAction("index");
};
return View(model);
}
这里添加了一个私有方法 ProcessUploadedFile(),
/// <summary>
/// 上传图片私有方法
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
private string ProcessUploadedFile(StudentEditViewModel model)
{
string uniqueFileName = null;
if (model.Photos.Count > 0)
{
foreach (var photo in model.Photos)
{
//必须将图片文件上传到wwwroot的images/avatars文件夹中
//而要获取wwwroot文件夹的路径,我们需要注入ASP.NET Core提供的webHostEnvironment服务
//通过webHostEnvironment服务去获取wwwroot文件夹的路径
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "images", "avatars");
//为了确保文件名是唯一的,我们在文件名后附加一个新的GUID值和一个下划线
uniqueFileName = Guid.NewGuid().ToString() + "_" + photo.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
//因为使用了非托管资源,所以需要手动进行释放
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
//使用IFormFile接口提供的CopyTo()方法将文件复制到
//wwwroot/images/avatars文件夹
photo.CopyTo(fileStream);
}
}
}
return uniqueFileName;
}
这是一个通用方法,很适合作为工具方法。该方法中唯一要注意的是,我
们使用了FileStream,这是一个非托管资源,因此需要使用using来进行内存的释放,否
则会出现以下异常。
System.IO.IOException
HResult=0x80070020
Message=The process cannot access the file 'C:\Source\
MockSchoolManagement\wwwroot\images\avatars\93308bf7-ccb0-4966-9aa7-
5f23324a170b_man1.png' because it is being used by another process.
Source=System.IO.FileSystem
要复现该错误,只需要将using(){}删除,然后对同一个学生进行连续两次图片修改操
作即可。