C# Net6 Ant Design of Blazor + WebApi实现文件上传与下载
0、开发环境
- Visual Studio 2022
- 基于net6
- Ant Design Blazor
1、在Visual Studio 2022中安装AntDesign模版
dotnet new --install AntDesign.Templates
详情请参阅Ant Design Blazor官网。
2、在Visual Studio 2022中创建Ant Design Pro Blazor App项目
创建项目时选择Ant Design Pro Blazor App,如下图:
3、在Ant Design Blazor项目中开启Web Api支持
在修改Startup.cs,以支持对Web Api的支持
1、ConfigureServices方法中增加services.AddControllers();
2、Configure方法中增加endpoints.MapControllers();
详细代码如下:
namespace WebSiteApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration {
get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddAntDesign();
services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(sp.GetService<NavigationManager>().BaseUri)
});
services.Configure<ProSettings>(Configuration.GetSection("ProSettings"));
services.AddControllers(); //增加对WebApi支持
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
endpoints.MapControllers(); //增加对WebApi支持
});
}
}
}
4、在项目中增加Controllers目录和控制器类
在项目中增加Controllers目录,并在此目录下增加控制器类FilesController.cs实现文件上传下载API,代码如下:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
namespace WebConfigSiteApp.Controller
{
[ApiController]
[Route("/api/file")]
public class FilesController : ControllerBase
{
private IWebHostEnvironment env;
public FilesController(IWebHostEnvironment env)
{
this.env = env;
}
[HttpPost, Route("upload")]
public ResultModel UploadFile([FromForm] IFormCollection formCollection)
{
ResultModel result = new ResultModel();
result.Message = "success";
result.Code = 0;
result.Url = "/api/file/download";
try
{
string uploadPath = System.IO.Path.Combine(env.ContentRootPath, "upload");
if (!System.IO.Directory.Exists(uploadPath))
{
System.IO.Directory.CreateDirectory(uploadPath);
}
FormFileCollection fileCollection = (FormFileCollection)formCollection.Files;
foreach (IFormFile file in fileCollection)
{
string filePath = System.IO.Path.Combine(uploadPath, Wongoing.Common.Global.BackupFileName);
Console.WriteLine(filePath);
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
}
using (FileStream fs = new FileStream(filePath, FileMode.CreateNew))
{
file.CopyTo(fs);
fs.Flush();
}
break;
}
}
catch (Exception ex)
{
result.Code = 100;
result.Message = $"文件上传失败:{
ex.Message}!";
Wongoing.Log.LoggingService<FilesController>.Instance.Error($"文件上传失败:{
ex.Message}", ex);
}
return result;
}
/// <summary>
/// 下载文件
/// </summary>
[HttpGet, Route("download")]
[ProducesResponseType(typeof(FileResult), (int)HttpStatusCode.OK)]
public FileResult Download()
{
try
{
string filePath = System.IO.Path.Combine(this.env.ContentRootPath, "upload", Wongoing.Common.Global.BackupFileName);
Stream stream = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read);
FileStreamResult actionresult = new FileStreamResult(stream, new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"));
actionresult.FileDownloadName = Wongoing.Common.Global.BackupFileName;
return actionresult;
}
catch (Exception ex)
{
Wongoing.Log.LoggingService<FilesController>.Instance.Error($"文件下载失败:{
ex.Message}", ex);
return null;
}
}
}
public class ResultModel
{
public int Code {
get; set; }
public string Message {
get; set; }
public string Url {
get; set; }
}
}
1、为了获取当前站点的物理路径,此类通过构造方法注入了IWebHostEnvironment对象env,env.ContentRootPath表示当前站点根目录的物理路径。
2、Ant Design Blazor Upload组件的Action对应的文件上传接口参数类型为[FromForm] IFormCollection。
3、实现文件下载的API方法可以通过返回Microsoft.AspNetCore.Mvc.FileResult实现。
5、使用Ant Design Blazor Upload组件开发上传的UI页面
在项目中新增一个razor组件以实现文件上传,代码如下:
@namespace WebSiteApp.Pages.Sys
@page "/sys/sysbackup"
<PageContainer>
<Breadcrumb>
<Breadcrumb>
<BreadcrumbItem>首页</BreadcrumbItem>
<BreadcrumbItem>系统</BreadcrumbItem>
<BreadcrumbItem>系统备份</BreadcrumbItem>
</Breadcrumb>
</Breadcrumb>
<Content>
<span style="color:#FF0000">通过此功能实现对配置的备份和恢复!</span>
</Content>
<ChildContent>
<Card Title="系统备份">
<Row Gutter="16">
<AntDesign.Col Xl="new EmbeddedProperty{Span = 4}"
Lg="new EmbeddedProperty{Span = 4}"
Md="new EmbeddedProperty{Span = 4}"
Sm="4">
<Button Type="@ButtonType.Primary" Icon="copy" OnClick="DoBackup">系统配置备份</Button>
</AntDesign.Col>
<AntDesign.Col Xl="new EmbeddedProperty{Span = 4}"
Lg="new EmbeddedProperty{Span = 4}"
Md="new EmbeddedProperty{Span = 4}"
Sm="4" Style="padding-top:8px;">
<a href="/api/file/download" target="_blank" class="btn btn-primary" style='display:@(_disabledDownload ? "none": "block");'>下载备份文件</a>
</AntDesign.Col>
</Row>
</Card>
<Card Title="系统恢复">
<Row Gutter="16">
<AntDesign.Col Xl="new EmbeddedProperty{Span = 4}"
Lg="new EmbeddedProperty{Span = 4}"
Md="new EmbeddedProperty{Span = 4}"
Sm="4">
<Upload Name="files"
Action="/api/file/upload"
FileList="fileList"
BeforeUpload="BeforeUpload"
OnSingleCompleted="OnSingleCompleted">
<Button Type="@ButtonType.Primary" Icon="upload">
<span>上传备份的文件</span>
</Button>
</Upload>
</AntDesign.Col>
<AntDesign.Col Xl="new EmbeddedProperty{Span = 4}"
Lg="new EmbeddedProperty{Span = 4}"
Md="new EmbeddedProperty{Span = 4}"
Sm="4">
<Button Type="@ButtonType.Primary" Icon="rollback" Disabled="@_disabledRecover" OnClick="DoRecover">执行配置恢复</Button>
</AntDesign.Col>
</Row>
</Card>
</ChildContent>
</PageContainer>
@code {
RenderFragment icon = @<Icon Type="question-circle" Theme="outline"></Icon>;
}
1、Upload组件的Action属性指定文件上传接口(对应Controllers/FilesController.cs中的UploadFile的路由),在通过Upload组件操作文件上传时,会自动调用Action属性指定的Web Api。
2、下载文件,只需在a标签的href属性执行文件下载接口的访问路径就可,例:<a href=“/api/file/download” target=“_blank”>文件下载</a>