用JavaScript生成带Unicode字符的Excel CSV文件

17
我正在尝试使用JavaScript在客户端生成CSV文件。我按照这个stackoverflow问题的答案进行操作。我的内容中有Unicode字符(在我的情况下是希伯来字母)。
文件生成成功,但是当我在Excel中打开文件时,所有的Unicode字符都显示为奇怪字符。ASCII字符(英文和数字)则呈现正常。
奇怪的是,如果我在记事本中打开文件,则Unicode字符会显示完好。因此,我想这可能与Excel和我保存文件的方式有关。
有什么想法吗?

1
这可能是字节顺序标记。这个链接有帮助吗?https://dev59.com/AnVC5IYBdhLWcg3w4Vb6 - Jack Cole
是的,是的,是的!添加BOM前缀起作用了! - Shay Friedman
3个回答

40

根据Jack Cole的评论和此问题,解决我的问题的方法是在文件开头添加BOM前缀 (\uFEFF)。

这是可行的代码:

var csvContent = "...csv content...";
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", "data:text/csv;charset=utf-8,\uFEFF" + encodedUri);
link.setAttribute("download","report.csv");
link.click();

5

建议的解决方案在所有浏览器上都无法正常工作,但我找到了一种方法,在所有浏览器中使其正常工作(Chrome、Firefox、IE11甚至Edge,...不知道IE9-10是否可以,因为我不再拥有它们)。

我必须使用外部库来编码encoding.js,它与Unicode非常配合(我可以在Excel的CSV导出中看到我的独角兽表情符号),效果非常好。

所以这是代码:

data = new TextEncoder('utf-16be').encode(csvContent);
  
// create a Blob object for the download
const blob = new Blob(['\uFEFF', data], {
  type: 'text/csv;charset=utf-8';
});

// if we're using IE/Edge, then use different download call
if (typeof navigator.msSaveOrOpenBlob === 'function') {
  navigator.msSaveOrOpenBlob(blob, filename);
} else {
  // the next code will generate a temp <a /> tag that you can trigger a hidden click for it to start downloading
  const link = document.createElement('a');
  const csvUrl = URL.createObjectURL(blob);

  link.textContent = 'download';
  link.href = csvUrl;
  link.setAttribute('download', filename);

  // set the visibility hidden so that there is no effect on your web-layout
  link.style.visibility = 'hidden';

  // finally we will append the anchor tag and remove it after clicking it
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

就是这样,它可以在 IE / Edge / Chrome / Firefox 中工作。

enter image description here


1
"...我无法再访问它们了" --> https://developer.microsoft.com/zh-cn/microsoft-edge/tools/vms/ - balexandre

3
在一个Node/Express服务器上,我尝试了Shay的答案,但是我在头部得到了一个无效字符的错误。相反,我在回复正文的开头添加了\uFEFF,这样就可以工作了。
app.get('/', function (req, res) {
    var csv = Papa.unparse(...);
    res.set({
       'Content-Type': 'text/csv; charset=UTF-8',
       'Content-Disposition': 'attachment; filename="file.csv"',
    });
    res.send('\uFEFF' + csv)
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接