Javascript 到 csv 导出编码问题

IT技术 javascript csv export-to-csv
2021-03-01 11:37:45

我需要将 javascript 数组导出到 excel 文件并下载它我正在此代码中执行此操作。数据是一个javascript对象数组。

var csvContent = "data:text/csv;charset=utf-8,";
data.forEach(function(dataMember, index)
{
    dataString = dataMember.join(",");
    csvContent += index < data.length ? dataString+ "\n" : dataString;
}); 

var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "upload_data" + (new Date()).getTime() + ".csv");
link.click();

所有这些东西都可以正常工作,直到我拥有包含非英语字符(如西班牙语、阿拉伯语或希伯来语)的字符串属性。如何使用所有这些非 ASCII 值进行导出?

6个回答

您应该在文本的开头添加 UTF-8 BOM,例如:

var csvContent = "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURI(csvContent);

它在 Excel 2013 中对我有用。

演示小提琴

这对我有用,使用 FileSaver.js。我没有使用 URL 编码,而是这样做了: var blob = new Blob(['\ufeff' + csvString], {type: 'text/csv;charset=utf-8'});
2021-04-23 11:37:45
你能在 jsFiddle 或其他东西中提供一个完整的工作示例吗?
2021-04-30 11:37:45
非常感谢。超过 1 年我遇到了这个问题,但找不到正确的答案。
2021-05-02 11:37:45
在 Mac 上,我最终得到了这个 :( dropbox.com/s/a36t99fvo43xhfe/...
2021-05-09 11:37:45
@jlarson 你在这里:链接我使用了 Benoit Blanchon 的演示。
2021-05-11 11:37:45

您可以首先添加 BOM,使用此代码并尝试

var BOM = "\uFEFF"; 
var csvContent = BOM + csvContent;

然后用数据创建文件头:“text/csv;charset=utf-8”

这对我有用: csv = 'data:text/csv;charset=utf-8,\uFEFF' + csvContent;
2021-04-26 11:37:45
这在将我的东西转换为 blob 然后使用锚标记单击 hack 触发下载时对我有用: var downloadLink = document.createElement("a"); downloadLink.download = fileNameToSaveAs; downloadLink.href = window.URL.createObjectURL(textFileAsBlob); downloadLink.onclick = function (e) { document.body.removeChild(e.target); }; downloadLink.style.display = "none"; document.body.appendChild(downloadLink); downloadLink.click();
2021-05-03 11:37:45
这!花了很长时间才找到可行的方法。谢谢!
2021-05-09 11:37:45
Excel 现在可以ář正确显示 Unicode 字符谢谢
2021-05-11 11:37:45
太好了,这对我来说使用纯 JavaScript 很有效!
2021-05-15 11:37:45

Excel 在检测编码方面非常糟糕,尤其是 OSX 上的 Excel。

最好的解决方案是使用默认的 Excel 编码对 CSV 进行编码:windows-1252(也称为 ANSI,基本上是 ISO-8859-1 的子集)。

我在https://github.com/b4stien/js-csv-encoding 上放了一个完整的例子来说明如何做到这一点

两个主要部分是stringencoding(在 windows-1252 中对 CSV 的内容进行编码)和FileSaver.js(下载生成的 Blob)。

看起来像:

var csvContent = 'éà; ça; 12\nà@€; çï; 13',
    textEncoder = new TextEncoder('windows-1252');


var csvContentEncoded = textEncoder.encode([csvContent]);
var blob = new Blob([csvContentEncoded], {type: 'text/csv;charset=windows-1252;'});
saveAs(blob, 'some-data.csv');
太棒了,谢谢!浏览了大量 SO 页面和文档,寻找解决问题的方法,在打开并在 OSX 上将它们保存回 CSV 后,Excel 会破坏 CSV。这是唯一有效的方法。
2021-04-17 11:37:45
我遇到了类似的问题 - InDesign 的 DataMerge 顽固地拒绝显示我的特殊字符,无论我是否尝试过 UTF-8、UTF-16、UTF-16LE、制表符、逗号等。使用上面 b4stien 的 repo 中的文件,并调整他的示例,它完美地工作!值得注意的是,就我而言,我只需要在 Windows 上定位 Chrome。
2021-04-28 11:37:45
谢谢,@b4stien 我正在寻找上传的 CSV 文件的编码。用户可能以不同的语言上传。我怎样才能知道呢?我尝试了很多解决方案,但似乎对我没有任何作用。请问有什么帮助吗?
2021-05-11 11:37:45
它在当前版本中不起作用,我必须从此链接下载该版本。谢谢你保存它
2021-05-14 11:37:45
请注意,现在TextEncoder不再接受 utf-8 以外的任何编码。
2021-05-16 11:37:45

选项1

使用iconv-litelibrary 并将您的输出编码为 ascii,然后再将其发送回用户。例子:

var iconv = require('iconv-lite');
buf = iconv.encode(str, 'win1255'); // return buffer with windows-1255 encoding

选项 2

在文件头部写入UTF-8编码的BOM头。例子:

res.header('Content-type', 'text/csv; charset=utf-8');
res.header('Content-disposition', 'attachment; filename=excel.csv'); 
res.write(Buffer.from('EFBBBF', 'hex')); // BOM header

// rest of your code

选项 3

使用 base64 url​​ 格式,如data:text/csv;base64,77u/Zm9vLGJhcg0KYWFhLGJiYg==. 此方法也适用于客户端(IE10+、FF、Chrome、Opera、Safari)。

例如:

window.location = "data:text/csv;base64,77u/" + btoa("foo,bar\r\naaa,bbb");
我为您添加了一个新选项 - 选项 3。
2021-04-16 11:37:45
我正在使用express.js框架。在平面 node.js 上,您可以使用setHeader
2021-04-17 11:37:45
我不是在谈论节点。我使用的是纯客户端 javascript)
2021-04-24 11:37:45
es.write(new Buffer('EFBBBF', 'hex')); 不再使用。
2021-04-30 11:37:45
嘿,谢谢你的回复。你能举一个选项2的完整例子吗?.header() 方法究竟是什么?res 对象究竟是什么?
2021-05-07 11:37:45

不知何故发现带有 utf-16le 编码和 BOM 的 Tab-Separated-CSV 在 WIN/MAC Excel 上工作

遵循 b4stien 的回答,但对存档有所不同:

var csvContent = 'éà; ça; 12\nà@€; çï; 13',
    textEncoder = new TextEncoder('utf-16le');
var csvContentEncoded = textEncoder.encode([csvContent]);
var bom = new Uint8Array([0xFF, 0xFE]);
var out = new Uint8Array( bom.byteLength + csvContentEncoded.byteLength );
out.set( bom , 0 );
out.set( csvContentEncoded, bom.byteLength );
var blob = new Blob([out]);
saveAs(blob, 'some-data.csv');

使用 Linux /usr/bin/file 测试:

Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators
不幸的是,这不再起作用 => "注意:在 Firefox 48 和 Chrome 53 之前,编码类型标签被接受为 TextEncoder 对象的参数,从那时起,这两个浏览器都取消了对 utf-8 以外的任何编码器类型的支持, 以匹配规范。现在将忽略传递到 TextEncoder 构造函数的任何类型标签,并创建一个 utf-8 TextEncoder。” developer.mozilla.org/en-US/docs/Web/API/TextEncoder
2021-04-20 11:37:45
我已经添加成功const blob = new Blob([new Uint8Array(iconv_lite.encode(csvContent, "utf16-le", {addBOM: true}))]);然后saveAs(来自file-saver
2021-05-09 11:37:45