blazor 不得不說真是好東西,極大的提升了開發效率,很多的頁面交互功能基本上只需要寫很少的代碼就能實現了,而且還是無 js 實現,你也絕對沒有想到過,blazor 實現文件上傳是有多麼簡單!
先說結論:blazor 實現帶進度顯示的文件上傳真的很簡單!效果看圖:

實現這麼一個小功能,僅僅只花了不到 50 行的代碼就實現了,接下來就給大家分享下案例實現吧。
首先引入Tewr.Blazor.FileReader包,这个包能够提供文件上传的流式读取,这样便可以实现在服务端对上传文件进行一边上传一遍写文件的操作。
配置依賴注入(站長註:這是 blazor server 模式,wasm 方式請查看文末倉庫文檔說明):
services.AddFileReaderService();
接下來我們先進行頁面布局,很簡單,再聲明兩個變量用於顯示進度和顯示圖片:
<input type="file" /><button>上传文件</button>
<div>
@if (!string.IsNullOrEmpty(_src)) {
<img src="@_src" width="600px" />
} else {
<p>@progress</p>
}
</div>
然後在組件中注入 ifilereaderservice 服務
@using Tewr.Blazor.FileReader @inject IFileReaderService fileReaderService;
為了讓文件框能夠和 c#代碼進行交互,所以需要將它通過 elementreference 引用起來:
<input @ref="inputTypeFileElement" type="file" /><button>上传文件</button>
<div>
@if (!string.IsNullOrEmpty(_src)) {
<img src="@_src" width="600px" />
} else {
<p>@progress</p>
}
</div>
@code { private ElementReference inputTypeFileElement; private string _src;
private string progress; }
給按鈕綁定事件,按鈕觸發後通過 filereaderservice 進行文件流的讀取,接下來便是常規的二進位數據 copy 操作,可以拿到文件的傳輸進度,計算之後便能顯示到頁面中
<button @onclick="ReadFile">上传文件</button>
public async Task ReadFile()
{
_src = "";
foreach (var file in await fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync())
{
await using var fileStream = await file.OpenReadAsync();
var buffer = new byte[2048];
var finalBuffer = new byte[fileStream.Length];
int count;
int totalCount = 0;
while ((count = await fileStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
Buffer.BlockCopy(buffer, 0, finalBuffer, totalCount, count);
totalCount += count;
progress = "文件上传中 " + (int)(totalCount * 100.0 / fileStream.Length) + "%";
StateHasChanged();
}
_src = $"data:image/jpg;base64,{Convert.ToBase64String(finalBuffer)}";
progress = "";
StateHasChanged();
}
}
完整代碼如下:
@page "/counter" @using Tewr.Blazor.FileReader @inject IFileReaderService
fileReaderService;
<input @ref="inputTypeFileElement" type="file" />
<button @onclick="ReadFile">上传文件</button>
<div>
@if (!string.IsNullOrEmpty(_src)) {
<img src="@_src" width="600px" />
} else {
<p>@progress</p>
}
</div>
@code { private ElementReference inputTypeFileElement; private string _src;
private string progress; public async Task ReadFile() { _src = ""; foreach (var
file in await
fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync()) {
await using var fileStream = await file.OpenReadAsync(); var buffer = new
byte[2048]; var finalBuffer = new byte[fileStream.Length]; int count; int
totalCount = 0; while ((count = await fileStream.ReadAsync(buffer, 0,
buffer.Length)) != 0) { Buffer.BlockCopy(buffer, 0, finalBuffer, totalCount,
count); totalCount += count; progress = "文件上传中 " + (int)(totalCount * 100.0
/ fileStream.Length) + "%"; StateHasChanged(); } _src =
$"data:image/jpg;base64,{Convert.ToBase64String(finalBuffer)}"; progress = "";
StateHasChanged(); } } }
站長插播:
文章首图演示的是一张不到1MB的图片,因为Tewr.Blazor.FileReader这个包提供文件上传的流式读取,上传大文件也是可以的,下面这是上传一个34.2MB的 ZIP 压缩包,Blazor 服务端模式:

demo 做的一般,可能 gif 看不出啥,只是為了證明這個包確實不錯,要實現大文件上傳,可把上面單包讀取大小改大一點,比如:512kb:
var buffer = new byte[1024*512];
如果看下方微軟 blazor 文件上傳文檔,把單包大小改成大於 20kb,頁面可能會卡一下,然後頁面自動刷新就把上傳操作給重置了,而使用這個包確沒這個問題,這個包很 nice。
ok,本文完
參考