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

时间:2013-07-24 14:02:07

标签: javascript export-to-csv

如果我们在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 for Creating a CSV in the Browser (not working - outputs window but no download)

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 个答案:

答案 0 :(得分:156)

始终存在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年7月)中工作正常。
也可以在Opera中使用,但不设置文件名(截至2013年7月) 似乎不适用于IE9(大惊喜)(截至2013年7月)

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


显然有a hack for IE10 and 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();
}

答案 1 :(得分:27)

@adeneo答案适用于Firefox和Chrome ...对于IE,可以使用以下内容。

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

答案 2 :(得分:15)

请参阅adeneo的回答,但不要忘记encodeURIComponent

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

另外,我需要做&#34; \ r \ n&#34;不只是&#34; \ n&#34;用于行分隔符。

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

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

答案 3 :(得分:7)

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

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

Github上提供了代码,文档和演示/游乐场。

享受:)

欢迎拉请求。

答案 4 :(得分:1)

请参阅adeneo的答案,但要在所有国家/地区的Excel中都可以使用此功能,应在文件的第一行添加“ SEP =”。这将在Excel中设置标准分隔符,并且不会显示在实际文档中

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

答案 5 :(得分:0)

我们可以使用javascript轻松创建和导出/下载带有任何分隔符的excel文件(在此答案中,我使用的是逗号分隔符)。我没有使用任何外部软件包来创建excel文件。

[1] pry(main)> x = 5
=> 5
[2] pry(main)> show-source x.+

From: numeric.c (C Method):
Owner: Integer
Visibility: public
Number of lines: 11

VALUE
rb_int_plus(VALUE x, VALUE y)
{
    if (FIXNUM_P(x)) {
  return fix_plus(x, y);
    }
    else if (RB_TYPE_P(x, T_BIGNUM)) {
  return rb_big_plus(x, y);
    }
    return rb_num_coerce_bin(x, y, '+');
}


[3] pry(main)> x = 5.0
=> 5.0
[4] pry(main)> $ x.+

From: numeric.c (C Method):
Owner: Float
Visibility: public
Number of lines: 16

static VALUE
flo_plus(VALUE x, VALUE y)
{
    if (RB_TYPE_P(y, T_FIXNUM)) {
  return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
    }
    else if (RB_TYPE_P(y, T_BIGNUM)) {
  return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
    }
    else if (RB_TYPE_P(y, T_FLOAT)) {
  return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
    }
    else {
  return rb_num_coerce_bin(x, y, '+');
    }
}