准备测试页面
使用 VS Code 打开 Module4\Tutorial_Lab_5 文件夹下的 MyWebApp 项目。
关于静态文件
图片、CSS、脚本(.js 文件)和 HTML 页面(.html 文件)都是静态(static)内容。静态内容不参与编译过程。当用户通过网页加载静态内容时,内容将直接返回至用户。
ASP.NET Core 程序中默认启用了静态文件中间件。通过 Startup.cs 文件 Configure 方法里面的 app.UseStaticFiles();
进行了配置。
现在介绍一下 wwwroot 文件夹。该文件夹表示 Web 程序的根目录(或 ~)。可以看到我们的 Default.png 就在 wwwroot 下的 images 文件夹里面,所以我们可以通过 Images/Default.png 在 HTML 源码中引用它。
实现文件上传
我们的任务是添加适当的视图和操作,使用户能够上传不同国家的国旗。
Controller
在 HomeController.cs 里面添加如下引用:
using System;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
再在 HomeController 里面添加 Action 代码:
private IHostingEnvironment _environment;
public HomeController(IHostingEnvironment env)
{
_environment = env;
}
[HttpGet]
public IActionResult UpdateNationalFlag(string code)
{
var country = DataSource.Countries
.SingleOrDefault(c => c.Code.Equals(code, StringComparison.CurrentCultureIgnoreCase));
return View(country);
}
[HttpPost]
public IActionResult UpdateNationalFlag(string code, IFormFile nationalFlagFile)
{
if (nationalFlagFile == null || nationalFlagFile.Length == 0)
return RedirectToAction(nameof(Index));
var targetFileName = $"{code}{Path.GetExtension(nationalFlagFile.FileName)}";
var relativeFilePath = Path.Combine("images", targetFileName);
var absolutFilePath = Path.Combine(_environment.WebRootPath, relativeFilePath);
var country = DataSource.Countries
.SingleOrDefault(c => c.Code.Equals(code, StringComparison.CurrentCultureIgnoreCase));
country.NationalFlagPath = relativeFilePath;
using (var stream = new FileStream(absolutFilePath, FileMode.Create))
{
nationalFlagFile.CopyTo(stream);
}
return RedirectToAction(nameof(Index));
}
env 参数的值由依赖注入设置。我们需要 _environment 字段的原因是因为我们需要 _environment.WebRootPath 的值来拼接上传文件的存储路径。
注:此处做了功能分隔,分离了 NationalFlag 的编辑和更新。[HttpGet] 将用户导向上传页面,[HttpPost] 执行上传更新操作。
View
在 Views/Home 文件夹下创建 UpdateNationalFlag.cshtml:
@model MyWebApp.Models.Country
<html>
<h1>Update Nation Flag</h1>
<form action="UpdateNationalFlag" method="POST" enctype="multipart/form-data">
<input type="hidden" name="code" value="@Model.Code"/>
<b>Code:</b><span>@Model.Code</span><br/>
<b>Name:</b><span>@Model.Name</span><br/>
<b>Continent:</b><span>@Model.Continent</span><br/>
<b>Choose Local File:</b>
<input type="file" name="nationalFlagFile"/><br/>
<input type="submit" value="Update"/>
</form>
</html>
代码中需要注意的点:
使用
action 属性名必须与 [HttpPost] 标注的操作名相同
提交 method 必须设置为 POST
enctype 属性必须设置为 multipart/form-data
unique 的国家 ID 必须一并返回给服务器。示例用的是 hidden 的 input,这也是最常用的方式
文件上传 input 的 name 属性必须与 Action 中的参数名一致
至此,我们可以通过手动输入 http://localhost:5000/home/UpdateNationalFlag?code=usa 进行国旗上传。当然为了便于使用,我们也可以更新 Index 页面,给 table 添加一行:
表头一行(header)添加
<th>Update</th>
表体(body)添加
<td>@Html.ActionLink("Update", "UpdateNationalFlag", new {code=c.Code})</td>
程序运行效果如下: