Експортуйте дані javascript у файл CSV без взаємодії сервера


77

Якби ми були на сервері nodeJS, ми могли б написати заголовок, встановити тип 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
Може бути , це допомагає: stackoverflow.com/questions/6796974 / ...
Vengarioth

URL-адреси даних @Vengarioth, безумовно, досить неясні, щоб мати можливість. Це, звичайно, не очевидно, я не бачив бібліотеки, яка це робить, і інша відповідь 2011 року говорить, що цього робити не можна.
Пол

подібні фокуси URL даних у відповідь на @Italo до stackoverflow.com/questions/4639372/export-to-csv-in-jquery
Paul

Відповіді:


161

Завжди є downloadатрибут HTML5 :

Цей атрибут, якщо він присутній, вказує на те, що автор має намір гіперпосилання використовувати для завантаження ресурсу, так що, коли користувач натискає на посилання, йому буде запропоновано зберегти його як локальний файл.

Якщо атрибут має значення, значення буде використано як ім'я попередньо заповненого файлу в запиті "Зберегти", що відкривається, коли користувач натискає на посилання.

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();

Скрипка

Протестовано в 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
Не вдалося зрозуміти, як встановити ім’я файлу, але я впевнений, що це якось можливо. Зазвичай це, attachment;filename=somefile.csvале це, здається, не працює для рядків csv?
adeneo

19
a.href = 'дані: вкладення / csv,' + encodeURIComponent (csvString);
Пол

1
Я підозрюю, що вони можуть бути перетворені назад у фактичний файл ... але не впевнений
Пол

1
Назва файлу у мене не працювала в Chrome. Це спрацювало, коли я змінив a.href на такий: a.href = window.URL.createObjectURL (new Blob ([csvString], {type: "attachment / csv"}));
Facio Ratio

1
@FacioRatio Google щось змінив у Chrome. порушення можливості встановити ім'я файлу. Дивіться: code.google.com/p/chromium/issues/detail?id=373182
Павло,

31

Відповідь @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
Я можу підтвердити, що це працює в IE11, і оновив свою бібліотеку html5csv, включивши підтримку IE 11 на основі цієї техніки. Я зарахував вашу публікацію в коментарі до коду. Дуже дякую.
Пол

15

Дивіться відповідь 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/



2

Див. Відповідь adeneo, але щоб зробити це в Excel у всіх країнах, слід додати "SEP =," у перший рядок файлу. Це встановить стандартний роздільник у Excel і не відображатиметься у фактичному документі

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

Я сумніваюся, що R або Pandas (Python) сподобається у файлі CSV.
Пол

1
@Paul Це може бути правдою, але в моєму випадку мені потрібно було створити файл CSV, який буде відкрито в Excel, і я хочу, щоб він відкривався презентабельно незалежно від місцевості. Якщо у вас є краще рішення для цього, я хотів би це почути!
Тиселій

1

Ми можемо легко створити та експортувати / завантажити файл excel із будь-яким роздільником (у цій відповіді я використовую роздільник комів) за допомогою javascript. Я не використовую жоден зовнішній пакет для створення файлу Excel.

    var Head = [[
        'Heading 1',
        'Heading 2', 
        'Heading 3', 
        'Heading 4'
    ]];

    var row = [
       {key1:1,key2:2, key3:3, key4:4},
       {key1:2,key2:5, key3:6, key4:7},
       {key1:3,key2:2, key3:3, key4:4},
       {key1:4,key2:2, key3:3, key4:4},
       {key1:5,key2:2, key3:3, key4:4}
    ];

for (var item = 0; item < row.length; ++item) {
       Head.push([
          row[item].key1,
          row[item].key2,
          row[item].key3,
          row[item].key4
       ]);
}

var csvRows = [];
for (var cell = 0; cell < Head.length; ++cell) {
       csvRows.push(Head[cell].join(','));
}
            
var csvString = csvRows.join("\n");
let csvFile = new Blob([csvString], { type: "text/csv" });
let downloadLink = document.createElement("a");
downloadLink.download = 'MYCSVFILE.csv';
downloadLink.href = window.URL.createObjectURL(csvFile);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.