谈谈如何在ASP.NET CORE 中实现密码查看附件和附件上传
前言
其实没啥好说的前言,就是强迫症说点什么。。。。。以下通过一个学习成果上传的场景进行说明如何操作。
数据库/实体/模型准备
建立一个实体模型,其中的属性包括密码属性以及一个附件路径属性。
public class Result
{
……
public string Password { get; set; }
public string Attachment { get; set; }
}
建立数据库,迁移等省略。不会看我之前的写的。总之最后建立的额数据库中将包含所上传文件的查看密码以及路径。
建议一个用于前端处理的视图模型
public class ResultViewModel
{
……
[Display(Name ="密码")]
public string Password { get; set; }
[Display(Name ="附件")]
public IFormFile Attachment { get; set; }
}
Attachment的类型为IFormFile,需要导入using Microsoft.AspNetCore.Http;
建立View
每天一个扫盲小技巧,有眼睛就能学废:
注意:要上传文件,form必须加上enctype="multipart/form-data"属性。
HTML表单如何打包数据文件是由enctype属性决定的。enctype有以下几种取值:
application/x-www-form-urlencoded:在发送前编码所有字符(默认)(空格被编码为’+’,特殊字符被编码为ASCII十六进制字符)
multipart/form-data:不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。因为只有使用enctype="multipart/form-data",表单才会把文件的内容编码到HTML请求中。
text/plain:空格被编码为“+” 加号,但不对特殊字符编码
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" type="password" placeholder="如需加密请输入密码" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Attachment" class="control-label"></label>
<input asp-for="Attachment" type="file" class="form-control" />
<span asp-validation-for="Attachment" class="text-danger"></span>
</div>
控制器逻辑
在控制器的Add方法中,添加存储文件的代码,然后将存储路径(附件)和密码保存到数据库中。
注意:需要先在wwwroot下新建一个file文件夹
首先方法参数增加[FromServices]IHostingEnvironment env,(需导入要using Microsoft.AspNetCore.Hosting; HostingEnvironment服务为我们提供了一个WebRootPath属性,该属性提供了wwwroot文件夹的绝对路径。
[HttpPost]
public async Task<IActionResult> Add([FromServices]IHostingEnvironment env, ResultModel model)
{
//指前端那些表单验证无效/失败
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
string filename = string.Empty;//存储路径
if (model.Attachment != null)
{
//文件操作类需要导入using System.IO;
filename = Path.Combine("file", Guid.NewGuid().ToString() + Path.GetExtension(model.Attachment.FileName));
using (var stream = new FileStream(Path.Combine(env.WebRootPath, filename), FileMode.CreateNew))
{
model.Attachment.CopyTo(stream);
}
}
await _resultRepository.AddAAsync(new Result
{
StuName = model.StuName,
Title = model.Title,
Discription = model.Discription,
TypeId=model.TypeId,
Create = DateTime.Now,
Password = model.Password,
Attachment = filename
});
return RedirectToAction("index");
}
public async Task<IActionResult> Detail(int id)
{
var result = await _resultRepository.GetByIdAsync(id);
if (!string.IsNullOrEmpty(result.Password))//如果设置了密码
{
return View();//即是Model=Null
}
return View(result);//没有设置密码,则查看全部字段数据
}
[HttpPost]
public async Task<IActionResult> Detail(int id, string password)
{
var result = await _resultRepository.GetByIdAsync(id);
if (!result.Password.Equals(password))
{
return BadRequest("密码错误,返回重新输入");
}
return View(result);
}
展示附件以及密码查看
@model ResultUploadSystem.Models.Result
@{
ViewData["Title"] = "Detail";
}
<h1>Detail</h1>
<div>
<h4>Result</h4>
<hr />
<dl class="row">
@if (Model == null)
{
<form method="post" asp-action="Detail">
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" type="password" placeholder="请输入密码" class="form-control" />
</div>
<p>
<button type="submit" class="btn text-center">查看</button>
</p>
</form>
}
else
{
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.StuName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.StuName)
</dd>
。。。。。。省略一些不相干的属性
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Password)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Attachment)
</dt>
<dd class="col-sm-10">
@*@Html.DisplayFor(model => model.Attachment)*@
@if (!string.IsNullOrEmpty(Model.Attachment))
{
<a href="~/@Model.Attachment">下载</a>
}
</dd>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>
}
</dl>
大概将以下流程:这里面在控制器中的Add方法中,实现了向数据库中写入文件路径以及密码。在Detial方法中实现了对于改Result的展示,假如存在有附件并且存在密码,则输入密码跳转查看,提供下载。