viernes, 17 de julio de 2015

Descargar datos en formato CSV del lado del Cliente (javascript)

Introducción


La introducción la pongo solo para darles a conocer el por qué decidí hacer esta entrada en mi blog, si quieren ver directamente el código, favor ir a la siguiente sección.

Pues hace unos días necesitaba hacer la descarga de un archivo CSV desde el lado del cliente, encontré varias opciones pero la moyoría funcionaba únicamente para navagadores no-Internet Explorer. Esto era un problema ya que funcionalidad debía ser multi plataforma. Después de un tiempo encontre una opción para IE con el inconveniente de que abría un dialog de "Save As", que no era lo que estaba buscando, y además IE solo permite descargar contenido "Html/text" quitándole por completo la extensión al archivo y dejando únicamente las opciones "Html/text". Por supuesto, aún así se puede descargar el contenido como CSV especificando el nombre del archivo junto con la extensión .csv entre comillas, sin embargo, esto no es para nada práctico para el usuario. Lo curioso de esto es que, en la mayoría de los blogs, decían que era la única forma de hacerlo. Pues si hay otra forma y es la siguiente:

Procedimiento


Primero debemos convertir los datos de Object/Json a contenido CSV. Para este ejemplo utilizaremos un Object, sin embargo, un objeto Json puede ser convertido facilmente a object mediante JSON.parse(). Para realizar esta conversión utilizamos el siguiente código:

function convertDataToCsv(objectData)
{
    var csvData = '';
    var row = '';

    for (var index in objectData[0])
    {
 row += index + ',';
    }
    row = row.slice(0, -1);
    csvData += row + '\r\n';

    for (var i = 0; i < objectData.length; i++)
    {
 var row = '';
 for (var index in objectData[i])
 {
     var arrValue = objectData[i][index] == null ? '' : '="' + objectData[i][index] + '"';
     row += arrValue + ',';
 }
 row.slice(0, row.length - 1);
 csvData += row + '\r\n';
    }
    return csvData;
}


Como segundo punto, debemos convertir el contenido CSV a an objeto Blob mediante:

var blobContent = new Blob([convertDataToCsv(objectData)], { type: 'text/csv;charset=utf-8;' });


Como tercer punto, detectar el navegador que estamos utilizando. Para esto existen muchas formas de hacerlo, una de ellas es la siguiente:

function isInternetExplorer() 
{
    var ua = window.navigator.userAgent;
    var msie = ua.indexOf("MSIE ");

    if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))
  return true;
            
    return false;
}


Y por último, dependiendo del navegador, realizamos lo siguiente:

if(isInternetExplorer())
{
    navigator.msSaveBlob(blobContent, 'file.csv');
}
else
{
    var link = document.createElement('a');
    link.href = URL.createObjectURL(blobContent);
    link.style.visibility = 'hidden';
    link.download = 'file.csv';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

Espero que a alguien le sea de ayuda.