C
C#10mo ago
Davide Dunne

Blazor: CSV exported is empty

Hi, I'm using CsvHelper to export a list of objects to a csv and then make the use download, the file gets downloaded but it's empty.
5 Replies
Davide Dunne
Davide DunneOP10mo ago
@using System.IO
@using CsvHelper
@using System.Globalization
@inject IJSRuntime JS
@code {
/// <summary>
/// Export to CSV from a Collection by clicking a button
/// Code obtained from: https://learn.microsoft.com/en-us/aspnet/core/blazor/file-downloads?view=aspnetcore-6.0#download-from-a-stream
/// https://joshclose.github.io/CsvHelper/getting-started/#writing-a-csv-file
/// </summary>
[Parameter, EditorRequired]
public IEnumerable<object>? objects { get; set; }
[Parameter, EditorRequired]
public string? FileName { get; set; }
[Parameter, EditorRequired]
public string? TextDisplay { get; set; }
private Stream GetFileStream()
{
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);

var csvWriter = new CsvWriter(streamWriter, culture: CultureInfo.InvariantCulture);
csvWriter.WriteRecords(objects);
return memoryStream;
}
private async Task DownloadFileFromStream()
{
var fileStream = GetFileStream();
var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", FileName, streamRef);
}
}
<MudIconButton Icon="@Icons.Material.Filled.Download" Color="Color.Secondary" Size="Size.Small" aria-label="Export to CSV" OnClick="DownloadFileFromStream">@TextDisplay</MudIconButton>
@using System.IO
@using CsvHelper
@using System.Globalization
@inject IJSRuntime JS
@code {
/// <summary>
/// Export to CSV from a Collection by clicking a button
/// Code obtained from: https://learn.microsoft.com/en-us/aspnet/core/blazor/file-downloads?view=aspnetcore-6.0#download-from-a-stream
/// https://joshclose.github.io/CsvHelper/getting-started/#writing-a-csv-file
/// </summary>
[Parameter, EditorRequired]
public IEnumerable<object>? objects { get; set; }
[Parameter, EditorRequired]
public string? FileName { get; set; }
[Parameter, EditorRequired]
public string? TextDisplay { get; set; }
private Stream GetFileStream()
{
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);

var csvWriter = new CsvWriter(streamWriter, culture: CultureInfo.InvariantCulture);
csvWriter.WriteRecords(objects);
return memoryStream;
}
private async Task DownloadFileFromStream()
{
var fileStream = GetFileStream();
var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", FileName, streamRef);
}
}
<MudIconButton Icon="@Icons.Material.Filled.Download" Color="Color.Secondary" Size="Size.Small" aria-label="Export to CSV" OnClick="DownloadFileFromStream">@TextDisplay</MudIconButton>
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);
}
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);
}
MarkPflug
MarkPflug10mo ago
First, you'd need to "reset" the memory stream after writing to it: memoryStream.Position = 0. Currently, the state of that stream is positioned at the end, since you just wrote data to it, so there are no bytes after the current position. Second, you might run into issues because you aren't flushing/disposing anything. CsvWriter and even StreamWriter might have internal buffering that would prevent everything from arriving in the MemoryStream until they are flushed, or closed. Be aware, that disposing the StreamWriter will close the MemoryStream by default, there is a constructor overload that accepts a boolean to tell it to leave the stream open.
Davide Dunne
Davide DunneOP10mo ago
Still not working :/
private Stream GetFileStream()
{
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);

var csvWriter = new CsvWriter(streamWriter, culture: CultureInfo.InvariantCulture);
csvWriter.WriteRecords(objects);

// Reset memory stream
memoryStream.Position = 0;

return memoryStream;
}
private async Task DownloadFileFromStream()
{
using var fileStream = GetFileStream();
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", FileName, streamRef);
}
private Stream GetFileStream()
{
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);

var csvWriter = new CsvWriter(streamWriter, culture: CultureInfo.InvariantCulture);
csvWriter.WriteRecords(objects);

// Reset memory stream
memoryStream.Position = 0;

return memoryStream;
}
private async Task DownloadFileFromStream()
{
using var fileStream = GetFileStream();
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", FileName, streamRef);
}
MarkPflug
MarkPflug10mo ago
Try this:
C#
private Stream GetFileStream()
{
var memoryStream = new MemoryStream();
using (var streamWriter = new StreamWriter(memoryStream, leaveOpen: true))
using (var csvWriter = new CsvWriter(streamWriter, culture: CultureInfo.InvariantCulture))
{
csvWriter.WriteRecords(objects);
}

// Reset memory stream
memoryStream.Position = 0;

return memoryStream;
}
C#
private Stream GetFileStream()
{
var memoryStream = new MemoryStream();
using (var streamWriter = new StreamWriter(memoryStream, leaveOpen: true))
using (var csvWriter = new CsvWriter(streamWriter, culture: CultureInfo.InvariantCulture))
{
csvWriter.WriteRecords(objects);
}

// Reset memory stream
memoryStream.Position = 0;

return memoryStream;
}
Davide Dunne
Davide DunneOP10mo ago
worked thanks, love you UwU
Want results from more Discord servers?
Add your server