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,本文完
參考