表格导出功能实践

逻辑追光
• 阅读 1101

表格导出分为静态导出与动态导出。

  • 静态导出是将当前已经渲染的表格项导出为指定的格式,可为.xls或.cvs。这种导出无需后端支撑,完全由前端实现。
  • 动态导出是通过将参数传与后端接口,该接口负责生成Blob或物理文件,并在Blob或物理文件路径返回后,由前端进行导出。

准备工作

无论用哪种方式进行导出,前端都需要准备一下触发器。
我们通常使用a标签的download标签来实现,十分简易。

// 然后通过a标签的download进行下载
var dispatchDownload = (fileName, href) => {
    var a = document.createElement('a');
    a.addEventListener('click', () => {
        a.download = fileName;
        a.href = href;
    });
    var e = document.createEvent('MouseEvents');
    e.initEvent('click', false, false);
    a.dispatchEvent(e);
};

静态导出

静态导出本质上是拼接字符串,只不过特别的是这些字符串符合了.xls, .cvs文件的解析规则。
什么格式的字符串会被解析为正确的文件?我在GridManager中先后尝试了两种方式。

html格式字符串

// 通过当前表格展示数据生成一组类似于下面的html string
var exportHTML = `
    <html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">
    <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>
    <body>
    <table>
        <thead>
            <tr>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
            </tr>
        </thead>
        <tbody>
            <tr><td>张三</td><td>男</td><td>22</td></tr>
            <tr><td>李四</td><td>男</td><td>23</td></tr>
            <tr><td>王五</td><td>女</td><td>24</td></tr>
            <tr><td>赵六</td><td>女</td><td>22</td></tr>
        </tbody>
    </table>
    </body>
    </html>`;

var href = `data:application/vnd.ms-excel;base64,${window.btoa(unescape(encodeURIComponent(exportHTML || '')))}`;

// 通过事先声明的dispatchDownload()函数进行下载
dispatchDownload('花名册.xls', href);

执行原理

  • 生成table html string
  • 通过btoa转换为base64编码
  • 拼接指定data类型的url
  • 通过a标签触发下载

使用这种方式存在导出文件无单元格分割线的问题,所以在GridManager v2.10.5版本中已经将该方式用 以逗号分割的字符串 方式替换。

以逗号分割的字符串

// 需要通过当前表格展示数据生成一组以逗号分割的字符串。
var exportStr = `姓名,性别,年龄\r\n张三,男,22\r\n李四,男,23\r\n王五,女,24\r\n赵六,女,22`;

// .cvs: data:text/csv, .xls: application/vnd.ms-excel
var href = `data:application/vnd.ms-excel;charset=utf-8,\ufeff${encodeURIComponent(exportStr)}`;

// 通过事先声明的dispatchDownload()函数进行下载
dispatchDownload('花名册.xls', href);

执行原理

  • 生成以逗号分割的字符串
  • 通过encodeURIComponent转义编码
  • 拼接指定data类型的url
  • 通过a标签触发下载

注意: 以上两种方式都属于纯前端操作,所导出的文件并非真实文件,在打开时会要求进行来源确认。

动态导出

动态导出需要后端提供接口,并根据接口返回不同的数据进行导出。

文件路径

var getHref = () => {
    // 我们假设现在有一个/download接口,该接口返回了文件地址
    // http.get('/download'); // 假装调了下接口
    return 'http://develop.lovejavascript.com/test.xlsx';
};

dispatchDownload('花名册', getHref());

这种方式对前端来言最为简易,只需调用接口并将接口返回的url通过a标签进行下载即可。
但是使用这种方式,后端需要在服务器上生成真实的文件。
前端是简单了,但后端不仅需要提供文件服务,还需要对生成的文件进行定期清理。
所以,后端小哥一般不会喜欢这种方式。
那么,后端小哥喜欢什么?
当然是文件流了。

文件流

对于后端返回的文件流,前端使用Blob方式进行导出。在调用后端接口时,需要指定request headers: {responseType: 'blob'}
var getBlog = () => {
    // 我们假设现在有一个/download接口,该接口返回了文件流
    // http.get('/download', headers: {responseType: 'blob'}); // 假装调了下接口
    return blob;
}

// 为防止返回数据不可用,验证一下
var blog = getBlog();
if (Object.getPrototypeOf(blob) === Blob.prototype) {
    // 通过URL.createObjectURL()将Blob转换为URL。这个新的URL对象表示指定的File对象或Blob对象。
    var url = URL.createObjectURL(blob);

    // 进行下载
    dispatchDownload('花名册', url);
}

使用这种方式,对于前端来说也没有什么工作量。
而且对于后端也无需创建物理文件,仅需生成文件流并将流返回。
在发送请求时所指定的headers: {responseType: 'blob'},仅是告诉浏览器前端所期望获取到的返回格式,对于后端来说无需特殊处理。

最后,推荐一个表格组件GridManager。以上导出的四种方式,可以到组件源码进行查看。

点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
vue+iview中的table表格导出excel表格
一、iveiw框架中table中有exportCsv()方法可以导出.csv后缀文件,类似于excel文件,但是并不是excel文件。二、实现table表格导出excel文件利用Blob.js和Export2Excel.js两个文件实现  1.Blob.js和Export2Excel.js文件    链接:https://pan.baid
Wesley13 Wesley13
3年前
java导出多sheet的excel
excel工具类,适合单sheet或多sheet的excel表格导出packageUtil;importorg.apache.poi.hssf.usermodel.HSSFWorkbook;importorg.apache.poi.ss.usermodel.\;importjavax.servlet.ServletOut
Wesley13 Wesley13
3年前
JAVA导出EXCEL表格
hi~好久不见小伙伴们,最近比较忙,没什么时间写,今天给大家分享的是JAVA如何导出EXCEL表格,因为最近有做这样一个功能,所以分享出来,如有不对之处,敬请指正。在许多企业办公系统中,经常会有用户要求,需要对数据进行统计并且可以直接下载Excel文件,这样子的话,既然客户提出了要求,我们就应该去满足吖,毕竟客户是上帝嘛,那么我们如何去实现呢?且看我
Wesley13 Wesley13
3年前
oracle expdp导入导出部分表
导出命令:expdpsystem/pwddumpfile导出文件名.dump  tables用户名.表名1,用户名.表名2  system/pwd   为管理员账号 tables             你要导出数据库用户名.你要导出的表       默认会导出到oracle安装目录:/u01/app/or
Stella981 Stella981
3年前
Confluence 导出为 PDF 格式
使用Confluence的空间导出功能,你可以将多个页面或者整个Confluence站点转换为PDF文件。希望使用空间导出功能,你需要导出空间(ExportSpace)权限。请查看指派空间权限指南。希望导出一个空间或者选择的页面为PDF:进入空间然后在边栏中选择选择空间工具内容工具(
Stella981 Stella981
3年前
Android so注入(inject)和Hook技术学习(二)——Got表hook之导入表hook
  全局符号表(GOT表)hook实际是通过解析SO文件,将待hook函数在got表的地址替换为自己函数的入口地址,这样目标进程每次调用待hook函数时,实际上是执行了我们自己的函数。  GOT表其实包含了导入表和导出表,导出表指将当前动态库的一些函数符号保留,供外部调用,导入表中的函数实际是在该动态库中调用外部的导出函数。  这里有几个关键点要
Wesley13 Wesley13
3年前
MySQL 查询结果保存为CSV文件
点击上方“IT共享之家”,进行关注回复“资料”可获赠IT学习福利MySQL支持将查询结果直接导出为文本格式,格式如下:intooutfile‘导出的目录和文件名’          指定导出的目录和文件名fieldst
Stella981 Stella981
3年前
Cocos Creator导出场景和预制的问题
CocosCreator支持导出当前项目中的场景和预制为另一个项目所用:1,选择要导出的场景或者预制;2,选择要导出到的目标文件夹位置并进行可能的重新命名;3,导出一个压缩文件.zip。4,解压压缩文件.zip,然后可以拖动其中的内容到目标项目指定位置进行使用即可。但是也有一些小问题:1,
晴雯 晴雯
2年前
SQLite数据库管理工具 SQLPro SQLite Mac版 v2023.45 破解版下载
SQLite数据库管理工具SQLProforsqlitemac是Mac和iOS平台数据库管理软件。还支持语法高亮、自动完成、代码折迭、导入和导出数据等功能,并且可以连接到本地或远程SQLite数据库。将数据导出到csv,mysql,xml或json。与SQ
Python进阶者 Python进阶者
1年前
Typora导出的PDF目录标题自动加编号
Typora导出的PDF目录标题自动加编号在Typora主题文件夹增加如下文件后,标题便自动加上了编号:https://gitcode.net/as604049322/blogdata//blob/master/base.user.css例如:但是导出的P
sum墨 sum墨
10个月前
《优化接口设计的思路》系列:第十一篇—表格的导入导出接口优化
在后端开发中,我们经常处理增删改查的接口,这些操作已经非常熟悉了。然而,有时产品经理会要求增加一个表格数据的导入和导出功能,让用户可以离线处理数据。这类操作也很常见,但处理起来不太简单。尽管一些前端表格组件可以直接实现这类功能,但往往不够灵活,因为前端的数据通常已经过处理。如果要获取原始数据,还是得依靠后端处理。
逻辑追光
逻辑追光
Lv1
我是街上的游魂,你是闻到我的人。
文章
4
粉丝
0
获赞
0