Skip to content

Blazor Server File Streaming freezes UI #33752

Closed
@dotnetspark

Description

@dotnetspark

Background

I have a Blazor Server hosting model with an API to download files. It could be fetched from a Azure blob storage or file share. In the Client I have a page with a button that calls the API to download a file. As of now, everything works, but the UX is bad since the UI is frozen until the current download is completed. If the file to download is 1GB, UI will be frozen for a long time. Is there a way to improve this?

Server - File API

[HttpPost]
public async Task<ActionResult> Download([FromBody] FileModel model)
{
    try
    {
        var result = FileService.GetFileStream(model);
        var provider = new FileExtensionContentTypeProvider();
        if (!provider.TryGetContentType(xfRequest.FileFullName, out var contentType))
        {
            contentType = "application/octet-stream";
        }

        return File(result, contentType, xfRequest.FileFullName);
    }
    catch (Exception e)
    {
        // do something
    }
}

Client - index.js

function download(filename, bytesBase64) {
    var link = document.createElement('a');
    link.download = filename;
    link.href = "data:application/octet-stream;base64," + bytesBase64;
    document.body.appendChild(link); // Needed for Firefox
    link.click();
    document.body.removeChild(link);
}

Client - Shared - FileExtensions.cs

public static class FileExtensions
{
    public static async Task Download(this IJSRuntime js, string filename, byte[] data)
    {
        await js.InvokeVoidAsync("download", filename, Convert.ToBase64String(data));
    }
}

Client - Pages - Files

<button class="btn btn-primary" @onclick="Download" text="Download" />

\\ more code here

@code
{
    /* code left out here*/

    private async Task DownloadFile()
    {
        using (var response = await this.Http.PostAsJsonAsync<FileModel>("api/file/download", model))
        {
            var content = await response.Content.ReadAsByteArrayAsync();
            await JS.Download(model.FileName, content);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions