Closed
Description
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);
}
}
}