asp.net-core.net-coreblazorblazor-server-side

Troubles with InputFile component in Blazor (Server Side) .NET 6


I created simple Blazor component for pictures preview and upload. InputFile component is hidden and label is used as button to open choose file dialog. After file/image choosing I want to show the image on preview. I read the file end encode it to base64.

@using Microsoft.AspNetCore.Components.Forms
@inject IJSRuntime JSRuntime

<div class="m-2">        
    <InputFile style="display: none" id="productPictureInput" OnChange="HandleImageUpload" accept="image/*" />
    <label for="productPictureInput" class="btn btn-primary" style="cursor: pointer;" @onclick="TriggerFileInput">Add Image</label>
    @if (imagePreviewSrc != null)
    {
        <img src="@imagePreviewSrc" alt="Image preview" style="max-width: 200px; max-height: 200px; margin-left: 10px;" />
    }
</div>

@code {
    private string? imagePreviewSrc;

    private async void TriggerFileInput()
    {
        await JSRuntime.InvokeVoidAsync( "triggerClickEvent", "productPictureInput" );
    }

    private async void HandleImageUpload(InputFileChangeEventArgs e)
    {
        var imageFile = e.GetMultipleFiles().FirstOrDefault();
        if (imageFile != null)
        {
            var imageStream = imageFile.OpenReadStream();
            var buffer = new byte[imageStream.Length];
            await imageStream.ReadAsync(buffer);
            imagePreviewSrc = $"data:image/jpg;base64,{Convert.ToBase64String(buffer)}";
            StateHasChanged();
        }
    }
}

When I try the component on other Blazor page I get strange behavior. Load (choose file) dialog opens twice, image is only partly loaded (see attached image) and then I cannot change (choose other) image. partly loaded image

So please tip me what's is going wrong? Thanks.

JS function:

function triggerClickEvent(elementId) {
    document.getElementById(elementId).click();
}

It might be important to mention - it's ASP.NET MVC application, .NET 6. I added services.AddServerSideBlazor(); to Startup.cs.


Solution

  • To avoid opening choose file dialog twice we just need to add preventDefault:

        <label for="productPictureInput" class="btn btn-primary" style="cursor: pointer;"
               @onclick="TriggerFileInput" @onclick:preventDefault="true">Add Image</label>