javascriptencodeuricomponent

Dynamic CSV generated file downloads with UTF characters


So I have this code that creates a download dynamically from any array of objects with matching keys (I got it from another SO question, I'd love to credit the author, but I can't find the link):

var objectToCSVRow = function(dataObject) {
  var dataArray = new Array;
  for (var o in dataObject) {
    var innerValue = dataObject[o]===null?'':dataObject[o].toString();
    var result = innerValue.replace(/"/g, '""');
    result = '"' + result + '"';
    dataArray.push(result);
  }
  return dataArray.join(';') + '\r\n';
}

var exportToCSV = function(arrayOfObjects) {
  if (!arrayOfObjects.length) {
    return;
  }
  var csvContent = "data:text/csv;charset=utf-8,";

  // headers
  csvContent += objectToCSVRow(Object.keys(arrayOfObjects[0]));

  arrayOfObjects.forEach(function(item){
    csvContent += objectToCSVRow(item);
  }); 

  var encodedUri = encodeURI(csvContent);
  var link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", "customers.csv");
  document.body.appendChild(link); // Required for FF
  link.click();
  document.body.removeChild(link); 
}

It works fine, but when I try to include UTF-8 chars:

exportToCSV([{spanishChars:"ñé"}])

the encodeURI() function encodes them and I get this:

enter image description here

Is there a way I can create downloadable content without having to use encodeURI() or is there a way, at least, to have encodeURI() work with the special chars?

Thanks in advance


Solution

  • You need to add the BOM character on the first line of the CSV.

      var csvContent = "data:text/csv;charset=utf-8,";
      // add BOM - always on the first line of the csv
      csvContent += '\uFEFF';
      // headers
      csvContent += objectToCSVRow(Object.keys(arrayOfObjects[0]));