前端导出Excel文件过于庞大怎么处理

3,819 阅读2分钟

概述

背景

当我们在做导出Excel功能的时候,如果导出的文件过大,可能会导致浏览器崩溃,这里需要我们更懂浏览器,避免使用错误的方式实现文件导出

思路

浏览器的崩溃应该是运行的代码达到了浏览器允许的内存限制,我们要选择合适方式,避免操作占用太多内存,而是直接操作硬盘数据.

同时要考虑文件是后端生成还是前端生成,如果文件是后端生成,通过前端代码触发浏览器下载文件,是不会导致浏览器崩溃,

如果文件是前端生成那么我们要选用生成二进制对象Blob方式来生成文件,触发下载,避免浏览器崩溃

实现

错误的方式

方式1-通过浏览器生成文件(使用`encodeURIComponent)

**问题所在:**当encodeURIComponent对庞大的字符串做处理的时候,会让浏览器崩溃,可能超出了长度限制,达到了允许的内存限制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="download">下载</button>
</body>
<script>
    document.getElementById('download').onclick = function(){
        // excel的内容,这里的内容一般通过发请求,向后端获取数据
        var csvRows = [['序号','姓名'],['1','张三'],['2','李四']]
        // 生成excel的内容字符串
        var csvString = csvRows.join("\r\n");
        // 创建a标签给它赋值
        var a = document.createElement('a');
        a.href        = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csvString);
        a.target      = '_blank';
        a.download    = 'export.csv';
        // 模拟点击下载excel
        document.body.appendChild(a);
        a.click();
    }
</script>
</html>

预览

链接

正确的方式

以下2种方式,3种写法下载文件,文件过大都不会导致浏览器卡死.选择哪种方式,首先看文件是前端生成还是后端生成,然后看具体方式的优缺点来灵活选择

方式1-通过后端生成文件

后端可以将生成的文件通过文件流文件路径的方式告诉浏览器,前端通过表单提交页面路径跳转触发浏览器进行下载文件

方式1.1-通过form提交

优点:

  • 传统方式,兼容性好,不会出现URL长度限制问题

缺点:

  • 无法知道下载的进度
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="download">下载</button>
</body>
<script>
    document.getElementById('download').onclick = function(){
        // 创建表单
        const form = document.createElement('form');
        form.action = 'https://itcast-1255651667.cos.ap-chengdu.myqcloud.com/20220106133642.csv';
        form.method = 'get';
        form.style.display = 'none';
        // 插入到网页中
        document.body.appendChild(form);
        form.submit(); // 发送请求
        document.body.removeChild(form); // 发送完清除掉
    }
</script>
</html>
预览

链接

方式1.2-通过页面跳转

优点:

  • 简单方便直接

缺点:

  • 会出现URL长度限制问题
  • 无法知道下载的进度
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="download">下载</button>
</body>
<script>
    document.getElementById('download').onclick = function(){
        location.href = 'https://itcast-1255651667.cos.ap-chengdu.myqcloud.com/20220106133642.csv'
    }
</script>
</html>
预览

链接

方式2-通过浏览器生成文件(使用Blob)

后端可以将把文件数据通过api方式告诉浏览器,前端通过生成二进制对象Blob,并且使用a标签触发文件的下载

优点:

  • 通过生成二进制对象Blob文件大小限制小

缺点:

  • 有兼容性问题,IE10以下不可用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="download">下载</button>
</body>
<script>
    document.getElementById('download').onclick = function(){
        // excel的内容,这里的内容一般通过发请求,向后端获取数据
        var csvRows = [['序号','姓名'],['1','张三'],['2','李四']]
        // 生成excel的内容字符串
        var csvString = csvRows.join("\r\n");
        // 根据内容字符串生成Blob对象
        var csvData = new Blob([csvString], { type: 'text/csv' }); 
        // 创建a标签给它赋值
        var a = document.createElement('a');
        a.href        = URL.createObjectURL(csvData);
        a.target      = '_blank';
        a.download    = 'export.csv';
        // 模拟点击下载excel
        document.body.appendChild(a);
        a.click();
    }
</script>
</html>

预览

链接