CSV 文件本质是一个文本文件,字段值需要正确格式化以避免解析错误(例如,处理逗号、引号或换行符)。下面是一个具体的实现方法,包含字符串类型的格式化:
代码示例
// 假设有一个数据对象数组
const data = [
{ name: "John Doe", age: 30, city: "New York" },
{ name: "Jane Smith", age: 25, city: "Los Angeles, CA" },
{ name: "Bob \"The Builder\"", age: 40, city: "Chicago\nIL" }
];
// 格式化字符串,确保 CSV 安全
function formatCsvString(str) {
if (str === null || str === undefined) return '""';
str = String(str); // 转换为字符串
// 如果字符串包含逗号、引号或换行符,包裹在双引号中,并转义已有引号
if (str.includes(',') || str.includes('"') || str.includes('\n')) {
str = `"${str.replace(/"/g, '""')}"`;
}
return str;
}
// 生成 CSV 内容
function generateCsv(data) {
if (!data || data.length === 0) return '';
// 获取字段名称(表头)
const headers = Object.keys(data[0]);
// 生成表头行
const headerRow = headers.map(formatCsvString).join(',');
// 生成数据行
const rows = data.map(obj =>
headers.map(key => formatCsvString(obj[key])).join(',')
);
// 合并表头和数据行
return headerRow + '\n' + rows.join('\n');
}
// 导出 CSV 文件
function downloadCsv(data, filename = 'data.csv') {
const csvContent = generateCsv(data);
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const 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);
URL.revokeObjectURL(url);
}
// 调用示例
downloadCsv(data, 'example.csv');
关键点说明
-
字符串格式化 (
formatCsvString
)- 将字段值强制转换为字符串 (
String(str)
),确保即使是数字或其他类型也能正确处理。 - 如果值包含逗号(
,
)、双引号("
)或换行符(\n
),则用双引号包裹整个值,并将值中的双引号替换为两个双引号(""
),这是 CSV 文件的标准转义方式。 - 空值(
null
或undefined
)被格式化为""
。
- 将字段值强制转换为字符串 (
-
生成 CSV 内容 (
generateCsv
)- 从数据对象的第一个元素中提取字段名称作为表头。
- 遍历数据对象,将每个字段值通过
formatCsvString
格式化后,用逗号连接成一行。 - 表头和数据行之间用换行符(
\n
)分隔。
-
导出文件 (
downloadCsv
)- 使用
Blob
创建一个 CSV 文件内容。 - 通过创建临时
<a>
标签触发文件下载。 - 确保字符编码为
utf-8
,以支持特殊字符。
- 使用
生成的 CSV 示例
对于上述 data
,生成的 CSV 文件内容如下:
name,age,city
"John Doe",30,"New York"
"Jane Smith",25,"Los Angeles, CA"
"Bob ""The Builder""",40,"Chicago\nIL"
注意事项
- 编码问题:导出的 CSV 文件使用 UTF-8 编码。如果需要支持 Excel 打开时的中文字符不乱码,可以在
Blob
内容前添加 BOM(Byte Order Mark):const bom = '\uFEFF'; const blob = new Blob([bom + csvContent], { type: 'text/csv;charset=utf-8;' });
- 字段顺序:CSV 文件会按照
Object.keys(data[0])
的顺序生成字段,确保数据对象字段一致。 - 性能:对于大数据集,建议分批处理以避免内存问题。
- 浏览器兼容性:上述代码在现代浏览器(Chrome、Firefox、Edge 等)中均可正常工作。
如果需要 Node.js 环境
如果在 Node.js 中导出 CSV 文件,可以使用 fs
模块写入文件:
const fs = require('fs');
function saveCsv(data, filename = 'data.csv') {
const csvContent = generateCsv(data);
fs.writeFileSync(filename, csvContent, 'utf8');
}
// 调用示例
saveCsv(data, 'example.csv');
总结
通过 formatCsvString
函数确保字符串类型的正确格式化(处理逗号、引号、换行符等),结合 generateCsv
和 downloadCsv
函数,可以生成并导出符合 CSV 规范的文件。根据环境选择浏览器端或 Node.js 的实现方式即可。