无需服务器交互即可将 javascript 数据导出到 CSV 文件

IT技术 javascript export-to-csv
2021-01-30 16:23:11

如果我们在 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,但不用作下载。

我想我希望在底部选项卡中下载或在底部选项卡中下载一个空白的新窗口。

我想知道元标记是否正确,或者是否还需要其他标记。

有没有办法在不将其推送到服务器的情况下进行这项工作?

用于在浏览器中创建 CSV 的 JsFiddle(不起作用 - 输出窗口但没有下载)

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);
6个回答

总是有 HTML5download属性:

此属性(如果存在)表示作者打算使用超链接下载资源,以便在用户单击链接时将提示他们将其保存为本地文件。

如果该属性具有值,则该值将用作用户单击链接时打开的保存提示中的预填充文件名。

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 年 7 月)
也适用于 Opera,但不设置文件名(截至 2013 年 7 月)
似乎在 IE9 中不起作用(大惊喜)(截至 2013 年 7 月)

可以在此处找到
有关哪些浏览器支持下载属性的概述对于不支持的浏览器,必须在服务器端设置适当的标头。


显然IE10 和 IE11一个 hack,它不支持该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();
}
@FacioRatio 谷歌在 Chrome 中改变了一些东西。打破了设置文件名的能力。请参阅:code.google.com/p/chromium/issues/detail?id=373182
2021-03-25 16:23:11
a.href = 'data:attachment/csv,' + encodeURIComponent(csvString);
2021-03-30 16:23:11
无法弄清楚如何设置文件名,但我确信以某种方式是可能的。通常是这样,attachment;filename=somefile.csv但这似乎不适用于 csv 字符串?
2021-04-01 16:23:11
文件名在 Chrome 中对我不起作用。当我将 a.href 更改为以下内容时它起作用了: a.href = window.URL.createObjectURL(new Blob([csvString], { type: "attachment/csv" }));
2021-04-02 16:23:11
我怀疑它们可能会在实际文件中被转换回......但不确定
2021-04-09 16:23:11

@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');
}

我可以确认这在 IE11 中有效,并更新了我的库html5csv以包含基于此技术的 IE 11 支持。我在代码评论中记下了您的帖子。非常感谢。
2021-03-20 16:23:11

查看adeeo的答案,但不要忘记encodeURIComponent

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

另外,我需要为行分隔符执行 "\r\n" 而不仅仅是 "\n" 。

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

修改小提琴:http : //jsfiddle.net/7Q3c6/

一旦我将 JS 代码打包到一个小库中:

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

代码、文档和演示/操场在 Github 上提供。

享受 :)

欢迎拉取请求。

我们可以使用javascript轻松创建和导出/下载带有任何分隔符的excel文件(在这个答案中我使用逗号分隔符)。我没有使用任何外部包来创建 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();