我知道有很多类似的问题,但我需要使用JavaScript来完成。我正在使用Dojo 1.8
,并且已经将所有属性信息存储在一个数组中,它看起来像这样:
[["name1", "city_name1", ...]["name2", "city_name2", ...]]
你有什么想法可以在客户端将此导出为CSV
吗?
我知道有很多类似的问题,但我需要使用JavaScript来完成。我正在使用Dojo 1.8
,并且已经将所有属性信息存储在一个数组中,它看起来像这样:
[["name1", "city_name1", ...]["name2", "city_name2", ...]]
你有什么想法可以在客户端将此导出为CSV
吗?
您可以使用本地JavaScript完成此操作。您需要将数据解析为正确的CSV格式,如下所示(假设您正在使用一个数组来存储数据,就像您在问题中描述的那样):
const rows = [
["name1", "city1", "some other info"],
["name2", "city2", "more info"]
];
let csvContent = "data:text/csv;charset=utf-8,";
rows.forEach(function(rowArray) {
let row = rowArray.join(",");
csvContent += row + "\r\n";
});
或使用较短的方式(使用箭头函数):
const rows = [
["name1", "city1", "some other info"],
["name2", "city2", "more info"]
];
let csvContent = "data:text/csv;charset=utf-8,"
+ rows.map(e => e.join(",")).join("\n");
接下来,您可以使用JavaScript的window.open
和encodeURI
函数来下载CSV文件,方法如下:
var encodedUri = encodeURI(csvContent);
window.open(encodedUri);
window.open
方法访问数据URI时不支持这样做。为了实现这一点,你可以创建一个隐藏的<a>
DOM节点,并设置它的download
属性,如下所示:var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "my_data.csv");
document.body.appendChild(link); // Required for FF
link.click(); // This will download the data file named "my_data.csv".
根据上面的答案,我创建了这个函数,并在IE 11、Chrome 36和Firefox 29上进行了测试。
function exportToCsv(filename, rows) {
var processRow = function (row) {
var finalVal = '';
for (var j = 0; j < row.length; j++) {
var innerValue = row[j] === null ? '' : row[j].toString();
if (row[j] instanceof Date) {
innerValue = row[j].toLocaleString();
};
var result = innerValue.replace(/"/g, '""');
if (result.search(/("|,|\n)/g) >= 0)
result = '"' + result + '"';
if (j > 0)
finalVal += ',';
finalVal += result;
}
return finalVal + '\n';
};
var csvFile = '';
for (var i = 0; i < rows.length; i++) {
csvFile += processRow(rows[i]);
}
var blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
例如:https://jsfiddle.net/jossef/m3rrLzk0/。link.download !== undefined
不成立,可以回退到window.open
。 - MrYellowlink.style.visibility='hidden'
处会抛出异常,因为DOM属性是只读的。更多细节可以在http://updates.html5rocks.com/2015/04/DOM-attributes-now-on-the-prototype的“在严格模式下写入只读属性将抛出错误”部分找到。 - Blaise/** Convert a 2D array into a CSV string
*/
function arrayToCsv(data){
return data.map(row =>
row
.map(String) // convert every value to String
.map(v => v.replaceAll('"', '""')) // escape double colons
.map(v => `"${v}"`) // quote it
.join(',') // comma-separated
).join('\r\n'); // rows starting on new lines
}
例子:
let csv = arrayToCsv([
[1, '2', '"3"'],
[true, null, undefined],
]);
结果:
"1","2","""3"""
"true","null","undefined"
现在将其下载为文件:
/** Download contents as a file
* Source: https://dev59.com/questions/LWUp5IYBdhLWcg3w5KvV
*/
function downloadBlob(content, filename, contentType) {
// Create a blob
var blob = new Blob([content], { type: contentType });
var url = URL.createObjectURL(blob);
// Create a link to download it
var pom = document.createElement('a');
pom.href = url;
pom.setAttribute('download', filename);
pom.click();
}
下载:
downloadBlob(csv, 'export.csv', 'text/csv;charset=utf-8;')
URL: revokeObjectURL()
:https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL_static 和 document.body.removeChild(pom)
。 - undefined这个解决方案应该适用于 Internet Explorer 10+, Edge, 旧版和新版的 Chrome, FireFox, Safari, ++
这个被接受的答案在IE和Safari上不起作用。
// Example data given in question text
var data = [
['name1', 'city1', 'some other info'],
['name2', 'city2', 'more info']
];
// Building the CSV from the Data two-dimensional array
// Each column is separated by ";" and new line "\n" for next row
var csvContent = '';
data.forEach(function(infoArray, index) {
dataString = infoArray.join(';');
csvContent += index < data.length ? dataString + '\n' : dataString;
});
// The download function takes a CSV string, the filename and mimeType as parameters
// Scroll/look down at the bottom of this snippet to see how download is called
var download = function(content, fileName, mimeType) {
var a = document.createElement('a');
mimeType = mimeType || 'application/octet-stream';
if (navigator.msSaveBlob) { // IE10
navigator.msSaveBlob(new Blob([content], {
type: mimeType
}), fileName);
} else if (URL && 'download' in a) { //html5 A[download]
a.href = URL.createObjectURL(new Blob([content], {
type: mimeType
}));
a.setAttribute('download', fileName);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
location.href = 'data:application/octet-stream,' + encodeURIComponent(content); // only this mime type is supported
}
}
download(csvContent, 'dowload.csv', 'text/csv;encoding:utf-8');
运行此代码片段将会下载模拟数据为 csv 文件
感谢 dandavis https://dev59.com/GnHYa4cB1Zd3GeqPPLwL#16377813
iframe
部分可以被替换为只需使用location.href = ... - DanURL.createObjectURL
(以 URL
结尾,而不是 Url
)。 - Nathan Hinchey在Chrome 35更新中,下载属性的行为发生了变化。
https://code.google.com/p/chromium/issues/detail?id=373182
要在Chrome中使用,请使用以下内容:
var pom = document.createElement('a');
var csvContent=csv; //here we load our csv data
var blob = new Blob([csvContent],{type: 'text/csv;charset=utf-8;'});
var url = URL.createObjectURL(blob);
pom.href = url;
pom.setAttribute('download', 'foo.csv');
pom.click();
人们正在尝试创建自己的csv字符串,但在一些边缘情况下失败,例如特殊字符,这肯定是一个已经解决的问题,对吧?
papaparse - 用于JSON到CSV编码。使用Papa.unparse()
。
import Papa from "papaparse";
const downloadCSV = (args) => {
let filename = args.filename || 'export.csv';
let columns = args.columns || null;
let csv = Papa.unparse({ data: args.data, fields: columns})
if (csv == null) return;
var blob = new Blob([csv]);
if (window.navigator.msSaveOrOpenBlob) // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
window.navigator.msSaveBlob(blob, args.filename);
else
{
var a = window.document.createElement("a");
a.href = window.URL.createObjectURL(blob, {type: "text/plain"});
a.download = filename;
document.body.appendChild(a);
a.click(); // IE: "Access is denied"; see: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access
document.body.removeChild(a);
}
}
使用示例
downloadCSV({
filename: "filename.csv",
data: [{"a": "1", "b": "2"}],
columns: ["a","b"]
});
https://github.com/mholt/PapaParse/issues/175 - 有关浏览器支持讨论,请查看此评论。
我来这里是想找更符合RFC 4180标准的实现,但我没有找到,所以为了满足自己的需求,我做了一个(可能效率不高)的实现。我想与大家分享。
var content = [['1st title', '2nd title', '3rd title', 'another title'], ['a a a', 'bb\nb', 'cc,c', 'dd"d'], ['www', 'xxx', 'yyy', 'zzz']];
var finalVal = '';
for (var i = 0; i < content.length; i++) {
var value = content[i];
for (var j = 0; j < value.length; j++) {
var innerValue = value[j]===null?'':value[j].toString();
var result = innerValue.replace(/"/g, '""');
if (result.search(/("|,|\n)/g) >= 0)
result = '"' + result + '"';
if (j > 0)
finalVal += ',';
finalVal += result;
}
finalVal += '\n';
}
console.log(finalVal);
var download = document.getElementById('download');
download.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(finalVal));
download.setAttribute('download', 'test.csv');
希望这能帮助未来的某个人。这个方法同时结合了CSV的编码和下载功能。在我的jsfiddle示例中,你可以下载文件(假设使用HTML 5浏览器),或者在控制台中查看输出。
更新:
Chrome现在似乎失去了命名文件的功能。我不确定发生了什么或如何修复它,但每当我使用这段代码(包括jsfiddle),下载的文件现在都被命名为download.csv
。
@Default的解决方案在Chrome上完美运行(非常感谢!),但我在IE上遇到了问题。
这是一个解决方案(适用于IE10):
var csvContent=data; //here we load our csv data
var blob = new Blob([csvContent],{
type: "text/csv;charset=utf-8;"
});
navigator.msSaveBlob(blob, "filename.csv")
function convertToCsv(fName, rows) {
var csv = '';
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
for (var j = 0; j < row.length; j++) {
var val = row[j] === null ? '' : row[j].toString();
val = val.replace(/\t/gi, " ");
if (j > 0)
csv += '\t';
csv += val;
}
csv += '\n';
}
// for UTF-16
var cCode, bArr = [];
bArr.push(255, 254);
for (var i = 0; i < csv.length; ++i) {
cCode = csv.charCodeAt(i);
bArr.push(cCode & 0xff);
bArr.push(cCode / 256 >>> 0);
}
var blob = new Blob([new Uint8Array(bArr)], { type: 'text/csv;charset=UTF-16LE;' });
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, fName);
} else {
var link = document.createElement("a");
if (link.download !== undefined) {
var url = window.URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", fName);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
}
}
convertToCsv('download.csv', [
['Order', 'Language'],
['1', 'English'],
['2', 'Español'],
['3', 'Français'],
['4', 'Português'],
['5', 'čeština'],
['6', 'Slovenščina'],
['7', 'Tiếng Việt'],
['8', 'Türkçe'],
['9', 'Norsk bokmål'],
['10', 'Ελληνικά'],
['11', 'беларускі'],
['12', 'русский'],
['13', 'Українська'],
['14', 'հայերեն'],
['15', 'עִברִית'],
['16', 'اردو'],
['17', 'नेपाली'],
['18', 'हिंदी'],
['19', 'ไทย'],
['20', 'ქართული'],
['21', '中国'],
['22', '한국어'],
['23', '日本語'],
])
window.URL.revokeObjectURL(url);
将会导致网络错误。将其包装在 setTimeout()
中可以解决这个问题,参见这里。 - cdauthbArr.push(255, 254)
,因为 Excel 无法识别列。没有 BOM,Unicode 和列都可以被正确识别。我想知道其他版本的行为如何。 - tequilacat您可以使用以下代码将数组导出为CSV文件,使用Javascript。
这也处理特殊字符部分。
var arrayContent = [["Séjour 1, é,í,ú,ü,ű"],["Séjour 2, é,í,ú,ü,ű"]];
var csvContent = arrayContent.join("\n");
var link = window.document.createElement("a");
link.setAttribute("href", "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURI(csvContent));
link.setAttribute("download", "upload_data.csv");
link.click();
这里 是可工作的 jsfiddle 链接。
window.open
没有办法做到这一点。但是,你可以创建一个隐藏的链接,将其中的download
属性设置为你想要的文件名。然后点击这个链接就会下载以你想要的文件名命名的文件。我会将这个方法加入我的答案中。 - Defaultdocument.body.appendChild(link);
才能在火狐浏览器中获得完全的支持。 - Hardbyte[["Hello, world"]]
的情况下会失败。这将输出两列,而实际上应该只输出一列。 - aredridelencodeURIComponent()
函数是否有任何数据上限或其他限制? 我正在使用Chrome浏览器。 - Abhidemon