Web优雅的实现大数据量Excel导出

在做系统后台的时候,一般Excel表导出的方案是在服务器生成Excel表,返回给浏览器Excel文件地址,触发下载。当要导出的Excel行数达到数万行时,占用大量的服务器CPU或内存不说,还容易请求超时,还要改nginx配置。我就想,能否在前端浏览器创建Excel表呢?之后找到一个合适的js库可以实现这个功能:js-xlsx。
官方github地址:https://github.com/SheetJS/js-xlsx

实现思路

1、 浏览器创建xlsx
2、 每次ajax向后端请求若干行的数据,直到请求完成
3、 触发下载

本文省略php,web服务器等环境搭建步骤。看懂接下来代码实现,需要有一些js,html,PHP,ajax的一些相关知识。


1、js-xlsx库安装使用

本文使用npm安装js-xlsx,如果不用npm,可以直接去https://github.com/SheetJS/js-xlsx/releases下载压缩包(很卡,我的网下不动)。

创建项目目录后,执行以下命令,下载js-xlsx包:

npm init
npm install xlsx

创建index.html在header中引入




    
    demo
    
    


2、创建html页面元素

index.html


    


    导出进度:0%
    

浏览器显示:


image.png

3、添加js代码,初始化excel工作簿全局变量/excel sheet全局变量,绑定按钮点击事件


    



    导出进度:0%
    

get_data.php

TOTAL_ROW,
    ]);
    echo $json;
    exit;
}

//获取数据请求
$offset = intval($_GET['offset']);
$limit = intval($_GET['limit']);
//返回
echo json_encode(getData($offset, $limit));

//从数据库获取数据
function getData($offset, $limit)
{
    //此处一般情况是从数据库获取数据,这里为了简化直接生成数据
    $data = [];
    for ($i = 0; $i < $limit; $i++) {
        $lineNum = $offset + $i + 1; //行号
        $row = ["第${lineNum}行第1列数据", "第${lineNum}行第2列数据", "第${lineNum}行第3列数据", "第${lineNum}行第4列数据", "第${lineNum}行第5列数据", date('Y-m-d H:i:s')];
        $data[] = $row;
    }
    usleep(300000);//模拟耗时操作,暂停300ms
    return $data;
}

简单性能测试一下:

5w行数据,占用内存200MB,导出无压力


xlsx50w.PNG

20w行数据,占用内存600MB,导出无压力


xlsx20w.PNG

image.png

100w行数据,js报错,内存不够

结束语:

对比服务端生成excel的方案,我觉得有以下一些优点:

  • 性能更好,导出速度快
  • 有进度指示器,对用户友好
  • 分批生成,不会触发请求超时
  • 服务器压力大大降低
  • 和后端查询列表页面的逻辑基本一致,后端几乎不用增加功能直接用

缺点:前端逻辑比较复杂

注意:
  • 本文为原创,代码可以随意使用,无版权,转载请注明原地址
  • 本文代码不能直接用在生产环境,只用作流程演示,如需使用需要修改增加安全性等等。
  • 如果使用es6的asyncawait 语法,数据接收的代码比本例中的递归更简洁
  • 能生成excel表格最大行数只和客户端配置有关
  • js-xlsx还要很多用法,如调整单元格格式等,更多的用法可以参考官网
  • 本文前端代码在Chrome 77内核的浏览器下运行正常,其他浏览器兼容性本文不做探讨

你可能感兴趣的:(Web优雅的实现大数据量Excel导出)