概述
- 属于专栏-项目难点
- 重要程度:★★☆☆☆
背景
当我们在做导出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>