I'm trying to enable a user to click a button and download a CSV file with Blazor and I keep downloading an empty file, not sure what I'm doing wrong. I was able to reproduce this in a new Blazor project as well which I'll reference the code for here. My _Host.cshtml file looks like this:
<script>
window.downloadFileFromStream = async (fileName, contentStreamReference) => {
const arrayBuffer = await contentStreamReference.arrayBuffer();
const blob = new Blob([arrayBuffer]);
const url = URL.createObjectURL(blob);
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
URL.revokeObjectURL(url);
}
</script>
My Index.razor looks like this:
@page "/"
@using CsvHelper.Configuration
@using System.Globalization
@using System.Text
@using CsvHelper
@inject IJSRuntime JSRuntime;
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var csvFileName = "test.csv";
var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture)
{
HasHeaderRecord = true,
Delimiter = ",",
Encoding = Encoding.UTF8
};
DotNetStreamReference streamRef;
var records = new List<TestRecord>();
var record = new TestRecord {Id = 1, Name = "First"};
records.Add(record);
using (var mem = new MemoryStream())
using (var writer = new StreamWriter(mem))
using (var csvWriter = new CsvWriter(writer, csvConfig))
{
csvWriter.WriteHeader<TestRecord>();
await csvWriter.WriteRecordsAsync(records);
await writer.FlushAsync();
streamRef = new DotNetStreamReference(stream: mem);
await JSRuntime.InvokeVoidAsync("downloadFileFromStream", csvFileName, streamRef);
}
}
public class TestRecord
{
public int Id { get; set; }
public string Name { get; set; }
}
}
If I try and read the memory stream after writer.FlushAsync();
I'm able to read the record I added. Is anything glaringly obvious as to why my output file is always empty?