Search code examples
c#csv

jitbit/CsvExport in Blazor inserts »¿ to the first row, first column of file


I'm using Blazor Server in .net 8. I'm am trying to save a CSV file and am using jitbit/CsvExport to do it. The issue is that additional characters are being added to the first entry.

Image of CSV file contents with »¿ at the beginning

My razor.cs file looks like this:

private async Task ExportToCSV()
{
    var myExport = new CsvExport(includeColumnSeparatorDefinitionPreamble: false, includeHeaderRow: false);

    myExport.AddRow();
    myExport["Directions"] = "Directions";
    myExport["Leg"] = "Leg";
    myExport["LegTime"] = "Leg Time";
    myExport["Trip"] = "Trip";
    myExport["TripTime"] = "Trip Time";

    foreach (var direction in LoadedDrivingDirections)
    {
        var row = new object[5]
        {
                $"{direction.Maneuver} on {direction.Road}",
                direction.LegDistance.ToString("0.00"),
                TimeSpan.FromMinutes(direction.Time).ToString(@"hh\:mm"),
                direction.DistanceAtStart.ToString("0.00"),
                TimeSpan.FromMinutes(drivingDirectionViews.Where(w => w.Direction.Latitude == direction.Latitude).Select(s => s.TotalTime).FirstOrDefault()).ToString(@"hh\:mm")
        };

        myExport.AddRow();
        myExport["Directions"] = row[0];
        myExport["Leg"] = row[1];
        myExport["LegTime"] = row[2];
        myExport["Trip"] = row[3];
        myExport["TripTime"] = row[4];
    }

    await _js.SaveAs("ProMilesTrip.csv", myExport.ExportAsMemoryStream().ToArray());
}

And my js function is as follows:

function saveAsFile(filename, bytesBase64) {

if (navigator.msSaveBlob) {
    //Download document in Edge browser
    var data = window.atob(bytesBase64);
    var bytes = new Uint8Array(data.length);
    for (var i = 0; i < data.length; i++) {
        bytes[i] = data.charCodeAt(i);
    }
    var blob = new Blob([bytes.buffer], { type: "application/octet-stream" });
    navigator.msSaveBlob(blob, filename);
}
else {
    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);
}
}

Solution

  • The characters at the beginning of your CSV appear to be a byte order mark.

    Since you are using jitbit/CsvExport, the method CsvExport.ExportAsMemoryStream(Encoding encoding = null) has an optional parameter Encoding encoding:

     private readonly Encoding _defaultEncoding = Encoding.UTF8;
    
     public MemoryStream ExportAsMemoryStream(Encoding encoding = null)
     {
         MemoryStream ms = new MemoryStream();
    
         encoding = encoding ?? _defaultEncoding;
    

    The default value, Encoding.UTF8:

    returns a UTF8Encoding object that provides a Unicode byte order mark (BOM).

    Since you don't want that, you should pass in your own UTF8Encoding with the constructor parameter encoderShouldEmitUTF8Identifier set to false:

    _js.SaveAs("ProMilesTrip.csv", 
               myExport.ExportAsMemoryStream(encoding : new UTF8Encoding(false)).ToArray());