前端导出csv/excel文件的几种方式
前言经常做后管项目,里面必然会遇到的就是导出(下载)各种列表,一般就是excel或者csv格式的,有时候也会要求pdf格式,因为今天改了一个关于导出文件乱码的bug,就顺便小结一下。一、Excel和CSV格式文件在开始说导出(下载)方式之前,先来提一下Excel和csv格式是什么,有什么区别?直接下载Excel不就行了。可以仔细看一下下表,也可直接跳过看主要内容;ExceCSV这是一个二进制文件,
前言
经常做后管项目,里面必然会遇到的就是导出(下载)各种列表,一般就是excel或者csv格式的,有时候也会要求pdf格式,因为今天改了一个关于导出文件乱码的bug,就顺便小结一下。
一、Excel和CSV格式文件
在开始说导出(下载)方式之前,先来提一下Excel和csv格式是什么,有什么区别?直接下载Excel不就行了。可以仔细看一下下表,也可直接跳过看主要内容;
Exce | CSV |
---|---|
这是一个二进制文件,它保存有关工作簿中所有工作表的信息 | CSV代表Comma Separated Values 。这是一个纯文本格式,用逗号分隔一系列值 |
Excel不仅可以存储数据,还可以对数据进行操作 | CSV文件只是一个文本文件,它存储数据,但不包含格式,公式,宏等。它也被称为平面文件 |
Excel是一个电子表格,将文件保存为自己的专有格式,即xls或xlsx | CSV是将表格信息保存为扩展名为.csv的分隔文本文件的格式 |
保存在excel中的文件不能被文本编辑器打开或编辑 | CSV文件可以通过文本编辑器(如记事本)打开或编辑 |
在数据仓库中,对于详细的标准化模式规范来说,Excel是最好的 | 在数据仓库中,CSV遵循相当平坦,简单的模式 |
任何用于解析Excel数据的编程语言库通常都会更大,更慢,更复杂 | 任何编程语言来解析CSV数据是微不足道的,生成它是非常容易的 |
由于数值和文本之间没有明确的区别或区分,Excel可以使用自动格式化功能搞乱您的邮政编码和信用卡号码 | CSV是安全的,可以清楚地区分数值和文本。CSV不处理数据并按原样存储。 |
在Excel中,必须为每一行中的每一列都有一个开始标记和结束标记 | 在CSV中,只能编写一次列标题 |
Excel导入数据时消耗更多的内存 | 导入CSV文件可以更快,而且消耗更少的内存 |
在Excel中读取大文件的用户在END中更容易。此外,您还可以使用其他功能,例如选择要导入的单个单元格,自动转换日期和时间,读取公式及其结果,过滤器,排序等。 | 以CSV格式读取大文件不会像最终用户的Excel文件那样简单 |
除了文本,数据也可以以图表和图表的形式存储 | 每条记录都存储为一行文本文件,每一条新行都表示一个新的数据库行。CSV不能存储图表或图形 |
Excel文件只能用Microsoft Excel文档打开 | CSV可以用Windows中的任何文本编辑器打开,如记事本,MS Excel,Microsoft Works 9等 |
Excel可以连接到外部数据源来获取数据。您可以使用Excel中的自定义加载项来增加其功能。Excel允许使用详细的跟踪和评论功能查看数据。 | 所有这些功能在CSV中都是不可能的 |
作为开发人员,由于Excel是专有的,因此很难以编程方式操纵Excel文件。.NET以外的其他语言尤其如此 | 作为开发人员,以编程方式操作CSV很容易,因为毕竟它们是简单的文本文件。 |
Excel和CSV的主要区别:
-
CSV是纯文本文件,excel不是纯文本,excel包含很多格式信息在里面。
-
CSV文件的体积会更小,创建分发读取更加方便,适合存放结构化信息,比如记录的导出,流量统计等等。
-
CSV文件在windows平台默认的打开方式是excel,但是它的本质是一个文本文件。
-
一般用CSV主要用于导出导入表格。
二、前端根据后端返回导出文件
- 后端直接返回文件URL
前端请求接口返回一个正常静态文件URL, window.location.href=URL
这种是前端最简单的实现方式,但是缺点是耗资源,后端需要把数据转化为excel存起来,并且直接暴露连接。 - 后端直接返回一个outputStream数据流
前端请求接口返回一个数据流,前端实现浏览器将数据下载为文件;
axios.request({
url: url,
method: 'get',
params,
responseType: 'blob'
}).then(res => {
downLoadBlobFile(res.data,name,typeStr);
}).catch(err =>console.log(err))
上面的代码为vue中使用axios请求,怎么请求不重要,重要的是,responseType: 'blob’这一句,之后就可以对返回的blob二进制文件流做操作了。
什么是Blob呢,MDN官方解释:Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。
responseType值的类型可为如下:
值 | 数据类型 |
---|---|
’ ‘ | DOMString (这个是默认类型) |
arraybuffer | ArrayBuffer对象 |
blob | Blob对象 |
document | Document对象 |
json | JavaScript object, parsed from a JSON string returned by the server |
text | DOMString |
对于微软系浏览器(IE和Edge)和非微软系列浏览器采用两种不同的方式进行下载:
- IE和Edge 采用了 navigator.msSaveBlob 方法 此方法为IE10及以上特有,IE10以下勿采用
- 非微软浏览器 使用a标签的click事件进行下载
/*
*封装函数 downLoadFile.js
*data:二进制文件
*name:自定义文件名称
*typeStr:参数type为MIME类型(text/csv,application/vnd.ms-excel)
*/
downloadFile (data, name?,typeStr) {
if (!data) {
this.$message.error('解析数据为空!')
return
}
if (this.MyBrowserIsIE()) {
const blob = new Blob([data], { type: typeStr });
navigator.msSaveBlob(blob, name);
} else{
const blob = new Blob([data], { type: typeStr });
// 创建一个新的url,此url指向新建的Blob对象
let url = window.URL.createObjectURL(blob)
// 创建a标签,并隐藏改a标签
let link = document.createElement('a')
link.style.display = 'none'
// a标签的href属性指定下载链接
link.href = url
link.download = name?name:'下载列表'
link.click()
// URL.revokeObjectURL() 静态方法用来释放一个之前已经存在的、通过调用
window.URL.revokeObjectURL(url)
}
}
// 判断是否IE浏览器
MyBrowserIsIE() {
let isIE = false;
if (
navigator.userAgent.indexOf("compatible") > -1 &&
navigator.userAgent.indexOf("MSIE") > -1
) {
isIE = true; // ie浏览器
}
if (navigator.userAgent.indexOf("Trident") > -1) {
isIE = true; // edge 浏览器
}
return isIE;
}
这里需要注意的有两点:
- 我下载xls格式的type直接用的application/vnd.ms-excel,下载csv格式的直接用的text/csv;但是这种形式需要后端返回对应的excel流或者csv流,否则会有问题;
下载excel也可以用xlsx插件,具体可以去网上查找一下,好处就是可以操作excel表,缺点就是麻烦;
参数type为MIME类型,常见文档类型的MIME可参考MDN - 下载csv格式文件,Excel打开可能乱码,但是wps等正常。是因为微软家发明了一个bom头,只需要添加一个’\uFEFF就可以了,但是这个方法只兼容高版本Excel,经测试office2007不生效,office2010是可以的;关于bom头,大家可以看看这篇文章,(今天也是因为这个在windows的Excel打开csv文件是乱码这个bug )。
转换前: const blob = new Blob([data], { type: typeStr });
转换后: const blob = new Blob([’\uFEFF‘+data], { type: typeStr });
到这里前端根据后端返回的数据流操作浏览器下载就差不多了,但是一般导出的方法都写在公用的请求方法里面例如:
三、前端自己制作表格导出文件
导出文件大部分情况下是后端处理,有时候我们只需要js处理 该怎么做呢?主要就是获取根据table获取数据流,下面以拼接 csv格式为例,csv格式其实就是个纯文本文件,中间使用逗号或者换行符进行拼接; 也会有浏览器兼容问题,参考上文;
<script>
function exportCsv(obj) {
// 列表头部
let title = obj.title;
// 拿到对象数据的键,因为是一样的只去第一个即可
let dataKey = Object.keys(obj.data[0]);
// 列表内容
let data = obj.data;
let str = [];
// 拼接 enter 键或者换行符
str.push(obj.title.join(",") + "\r\n");
for (let i = 0; i < data.length; i++) {
let temp = [];
for (let j = 0; j < dataKey.length; j++) {
temp.push(data[i][dataKey[j]]);
}
// 拼接 enter 键或者换行符
str.push(temp.join(",") + "\r\n");
}
let blob = new Blob(['\uFEFF' + str.join('')], {
type: 'text/csv;charset=utf-8',
});
const url = window.URL.createObjectURL(blob)
let downloadLink = document.createElement("a");
downloadLink.href = url;
downloadLink.download = "test.csv"; // 导出的文件名
downloadLink.click();
window.URL.revokeObjectURL(url);
}
document.getElementById("export").onclick = function () {
exportCsv({
title: ["国家", "首都", "GDP"],
data: [
{country:'中国',city:'北京',gdp:'8千万亿'},
{country:'美国',city:'华盛顿',gdp:'7千万亿'},
{country:'巴西',city:'巴西利亚',gdp:'6千万亿'},
{country:'英国',city:'伦敦',gdp:'5千万亿'}
]
});
}
</script>
四、导出csv遇到的坑
- 导出CSV文件之后在excel中打开中文乱码,WPS没有问题。
解决方案: 添加一个bom头,’\uFEFF就可以了,但是这个方法只兼容高版本Excel,经测试office2007不生效,office2010是可以的; - 针对超过10位的数字用科学计数法展示;
解决方案: 这是excel自带的功能;可以让后端在纯数字里面拼接一个子符,缺点就是导出表格里面这个符号去不掉,需要在表格里面批量操作;也可以直接转换成xls或者xlsx格式,看需求吧!
参考文章 :
vue通用导出组件的实现导出 excel csv pdf
Node.js 解决 csv 文件乱码的两种办法
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)