Экспорт данных javascript в CSV файл без взаимодействия с сервером

Если бы мы были на узлеJS-сервере, мы могли бы написать заголовок, установить тип mime и отправить его:

res.header("Content-Disposition", "attachment;filename="+name+".csv"); 
res.type("text/csv");
res.send(200, csvString);

и из-за заголовков браузер создаст загрузку для названного файла csv.

Когда полезные данные генерируются в браузере, одно из решений для его получения в CSV файле - использовать ajax, загрузить его на сервер (возможно, при необходимости сохранить его там) и заставить сервер отправлять его с этими заголовками для загрузки csv в браузере.

Тем не менее, я бы хотел, чтобы 100% -ное решение для браузера не включало пинг-понг с сервером.

Поэтому мне пришло в голову, что можно открыть новое окно и попытаться установить заголовок с эквивалентом тега META.

Но это не работает для меня в недавнем Chrome.

Я получаю новое окно и содержит csvString, но не выполняет функцию загрузки.

Думаю, я ожидал получить либо загрузку на нижней вкладке, либо пустое новое окно с загрузкой на нижней вкладке.

Мне интересно, правильны ли метатеги или нужны ли другие теги.

Есть ли способ выполнить эту работу, не нажимая на сервер?

JsFiddle для создания CSV в браузере (не работает - выводит окно, но без загрузки)

var A = [['n','sqrt(n)']];  // initialize array of rows with header row as 1st item
for(var j=1;j<10;++j){ A.push([j, Math.sqrt(j)]) }
var csvRows = [];
for(var i=0,l=A.length; i<l; ++i){
    csvRows.push(A[i].join(','));   // unquoted CSV row
}
var csvString = csvRows.join("\n");
console.log(csvString);
var csvWin = window.open("","","");
csvWin.document.write('<meta name="content-type" content="text/csv">');
csvWin.document.write('<meta name="content-disposition" content="attachment;  filename=data.csv">  ');
csvWin.document.write(csvString);

Ответ 1

Всегда есть атрибут HTML5 download:

Этот атрибут, если он присутствует, указывает, что автор намеревается гиперссылку, которая будет использоваться для загрузки ресурса, чтобы, когда пользователь клики по ссылке, им будет предложено сохранить его как локальный файл.

Если атрибут имеет значение, значение будет использоваться как предварительно заполненный имя файла в приглашении "Сохранить", которое открывается, когда пользователь нажимает на ссылка.

var A = [['n','sqrt(n)']];

for(var j=1; j<10; ++j){ 
    A.push([j, Math.sqrt(j)]);
}

var csvRows = [];

for(var i=0, l=A.length; i<l; ++i){
    csvRows.push(A[i].join(','));
}

var csvString = csvRows.join("%0A");
var a         = document.createElement('a');
a.href        = 'data:attachment/csv,' +  encodeURIComponent(csvString);
a.target      = '_blank';
a.download    = 'myFile.csv';

document.body.appendChild(a);
a.click();

FIDDLE

Протестировано в Chrome и Firefox, отлично работает в самых новых версиях (по состоянию на июль 2013 года).
Также работает в Opera, но не устанавливает имя файла (по состоянию на июль 2013 года).
Кажется, не работает в IE9 (большой сюрприз) (по состоянию на июль 2013 года).

Обзор того, какие браузеры поддерживают атрибут загрузки, можно найти здесь
Для не поддерживающих браузеров необходимо установить соответствующие заголовки на сервере.


По-видимому, существует взломать для IE10 и IE11, который не поддерживает атрибут download (однако, Edge).

var A = [['n','sqrt(n)']];

for(var j=1; j<10; ++j){ 
    A.push([j, Math.sqrt(j)]);
}

var csvRows = [];

for(var i=0, l=A.length; i<l; ++i){
    csvRows.push(A[i].join(','));
}

var csvString = csvRows.join("%0A");

if (window.navigator.msSaveOrOpenBlob) {
    var blob = new Blob([csvString]);
    window.navigator.msSaveOrOpenBlob(blob, 'myFile.csv');
} else {
    var a         = document.createElement('a');
    a.href        = 'data:attachment/csv,' +  encodeURIComponent(csvString);
    a.target      = '_blank';
    a.download    = 'myFile.csv';
    document.body.appendChild(a);
    a.click();
}

Ответ 2

Ответ @adeneo работает для Firefox и chrome... Для IE можно использовать ниже.

if (window.navigator.msSaveOrOpenBlob) {
  var blob = new Blob([decodeURIComponent(encodeURI(result.data))], {
    type: "text/csv;charset=utf-8;"
  });
  navigator.msSaveBlob(blob, 'FileName.csv');
}

Ответ 3

См. ответ adeneo, но не забудьте encodeURIComponent!

a.href     = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csvString);

Кроме того, мне нужно было сделать "\ r\n" не просто "\n" для разделителя строк.

var csvString = csvRows.join("\r\n");

Пересмотренная скрипка: http://jsfiddle.net/7Q3c6/

Ответ 4

Как только я упаковал JS-код, сделав это в крошечную библиотеку:

https://github.com/AlexLibs/client-side-csv-generator

Код, документация и демонстрация/игровая площадка предоставляются на Github.

Наслаждайтесь:)

Запросы Pull приветствуются.