Is this the best way to upload files in Blazor?

Is this the best way to upload files in Blazor?

It must be said that Blazor is really a great thing, greatly improving development efficiency. Many page interaction functions can be implemented with only a small amount of code, and it's achieved without JS. You would never have imagined how simple it is to implement file uploads in Blazor!

Last updated 3/16/2022 7:36 AM
懒得勤快
5 min read
Category
Blazor
Tags
.NET Blazor Upload files Blazor Server

Blazor is truly a great tool, greatly improving development efficiency. Many page interaction features can be implemented with very little code, and without JavaScript. You would never have imagined how simple file uploads can be with Blazor!

Let's start with the conclusion: Implementing file uploads with progress display in Blazor is really simple! Check out the effect in the image:

This small feature was implemented in less than 50 lines of code. Now let me share the implementation with you.

First, introduce the Tewr.Blazor.FileReader package. This package provides streaming reading of file uploads, allowing you to write the file on the server side as it is being uploaded.

Configure dependency injection (Editor's note: This is for Blazor Server mode; for WASM mode, please refer to the repository documentation at the end of the article):

services.AddFileReaderService();

Next, let's lay out the page. It's very simple, with two variables declared to show progress and display the image:

<input type="file" /><button>Upload file</button>
<div>
  @if (!string.IsNullOrEmpty(_src)) {
  <img src="@_src" width="600px" />
  } else {
  <p>@progress</p>
  }
</div>

Then inject the IFileReaderService service into the component:

@using Tewr.Blazor.FileReader @inject IFileReaderService fileReaderService;

To allow the file input to interact with C# code, reference it via ElementReference:

<input @ref="inputTypeFileElement" type="file" /><button>Upload file</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; }

Bind an event to the button. When the button is triggered, read the file stream via fileReaderService. Then perform the usual binary data copy operation, which allows you to get the file transfer progress, calculate it, and display it on the page:

<button @onclick="ReadFile">Upload file</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 = "File uploading " + (int)(totalCount * 100.0 / fileStream.Length) + "%";
            StateHasChanged();
        }
        _src = $"data:image/jpg;base64,{Convert.ToBase64String(finalBuffer)}";
        progress = "";
        StateHasChanged();
    }
}

Complete code:

@page "/counter" @using Tewr.Blazor.FileReader @inject IFileReaderService
fileReaderService;

<input @ref="inputTypeFileElement" type="file" />
<button @onclick="ReadFile">Upload file</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 = "File uploading " + (int)(totalCount * 100.0
/ fileStream.Length) + "%"; StateHasChanged(); } _src =
$"data:image/jpg;base64,{Convert.ToBase64String(finalBuffer)}"; progress = "";
StateHasChanged(); } } }

Editor's interjection:

The image at the beginning of the article demonstrates uploading a file under 1MB. Since the Tewr.Blazor.FileReader package provides streaming reading, uploading large files is also possible. Below is an example of uploading a 34.2MB ZIP archive using Blazor Server mode:

The demo is simple, and the gif might not show much, but it proves this package is really good. To implement large file uploads, you can increase the single read chunk size, for example to 512KB:

var buffer = new byte[1024*512];

If you look at Microsoft's Blazor file upload documentation below, when you set the chunk size larger than 20KB, the page might freeze for a moment and then automatically refresh, resetting the upload operation. However, this package does not have that issue—it's very nice.

OK, that's all for this article.

References

Keep Exploring

Related Reading

More Articles
Same category / Same tag 11/6/2024

Why My Blog Website Returned to Blazor

The development of the blog website has gone through many hardships, with nearly 10 versions including MVC, Vue, Go, etc. Now it has returned to Blazor and adopted static SSR, resulting in a significant speed increase and successful launch.

Continue Reading
Same category / Same tag 2/29/2024

Data Display Can Also Be Done Like This in Winform

In the process of developing Winform, data display functionality is often required. Previously, the gridcontrol control was commonly used. Today, through an example, I would like to introduce how to use the table component from Ant Design Blazor for data display in a Winform Blazor Hybrid application.

Continue Reading
Same category / Same tag 2/29/2024

Can the Winform interface also look good?

A few days ago, I introduced using Blazor Hybrid in Winform, and mentioned that with the Blazor UI, our Winform programs can be designed to look better. Next, I will illustrate with an example of drawing in Winform Blazor Hybrid, hoping it helps you.

Continue Reading