easyExcel导出大数据量EXCEL文件,前端实现进度条或者遮罩层 ...

打印 上一主题 下一主题

主题 844|帖子 844|积分 2534

需求:页面点击导出,先按照页面条件去数据库查询,然后将查询到的数据导出。
题目:由于查询特别耗时,所以点击之后页面会看上去没有反应
方案1:就在点击之后在页面增长了一个进度条,等待后端查询结束之后,导出时,进度条会显示导出进度,导出结束之后进度条会消散。结果如下:

方案2:点击导出时前端增长一个遮罩层,遮罩层中心显示正在下载,导出完成后遮罩层消散,好处是可以既给用户提示,还可以阻止用户再次点击导出按钮。结果如下:

留意点:后端必要在响应头中设置ContentLength,前端必要用这个更新进度
  1. response.setContentLength(excelBytes.length); // 设置Content-Length
复制代码
方案1:进度条

html代码:
  1. <button type="button" id="export_btn" class="layui-btn btn_blue">导 出</button>
复制代码
  1. <!-- 进度条容器 -->
  2. <div id="progressContainer" style="display:none; margin-top:20px;">
  3.     <div id="progressBar"></div>
  4. </div>
  5. <!-- 显示下载进度百分比 -->
  6. <div id="progressText" style="display:none; margin-top:5px;">下载进度: 0%</div>
复制代码
css:
  1. #progressContainer {
  2.     width: 100%;
  3.     background-color: #f3f3f3;
  4.     border: 1px solid #ccc;
  5.     border-radius: 5px;
  6. }
  7. #progressBar {
  8.     width: 0%;
  9.     height: 20px;
  10.     background-color: #4caf50;
  11.     border-radius: 5px;
  12. }
复制代码
js代码:
  1. //进度条
  2. $('#export_btn').on('click', function () {
  3.    // 获取表单数据并构建FormData对象
  4.    var formData = $('#searchForm').serializeArray();
  5.    var form = new FormData();
  6.    $.each(formData, function () {
  7.        form.append(this.name, this.value);
  8.    });
  9.    // 添加额外的参数
  10.    form.append('publishFrom', '${RequestParameters.type}');
  11.     // 创建XHR对象
  12.     var xhr = new XMLHttpRequest();
  13.     xhr.open('POST', '路径/exportData', true);
  14.     xhr.responseType = 'blob'; // 设置响应类型为blob
  15.     // 显示进度条
  16.     $('#progressContainer').show();
  17.     $('#progressText').show();
  18.     $('#progressBar').css('width', '0%');
  19.     $('#progressText').text('下载进度: 0%');
  20.     // 设置请求头以模拟表单提交
  21.     // xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  22.     // 监听下载进度
  23.     xhr.onprogress = function (event) {
  24.         if (event.lengthComputable) {
  25.             var percentComplete = Math.round((event.loaded / event.total) * 100);
  26.             console.log('Loaded:', event.loaded, 'Total:', event.total);
  27.             $('#progressBar').css('width', percentComplete + '%');
  28.             $('#progressText').text('下载进度: ' + percentComplete + '%');
  29.         } else {
  30.             console.log('无法计算进度');
  31.         }
  32.     };
  33.     // 下载完成后处理
  34.     xhr.onload = function () {
  35.         if (xhr.status === 200) {
  36.             // 隐藏进度条
  37.             $('#progressContainer').hide();
  38.             $('#progressText').hide();
  39.             // 创建下载链接并触发下载
  40.             var blob = xhr.response;
  41.             var downloadUrl = URL.createObjectURL(blob);
  42.             var a = document.createElement('a');
  43.             a.href = downloadUrl;
  44.             // 从响应头中获取文件名
  45.             var disposition = xhr.getResponseHeader('Content-Disposition');
  46.             var fileName = '下载文件.xlsx';
  47.             if (disposition && disposition.indexOf('filename*=utf-8\'\'') !== -1) {
  48.                 var filenameRegex = /filename\*=utf-8''(.+)/;
  49.                 var matches = filenameRegex.exec(disposition);
  50.                 if (matches != null && matches[1]) {
  51.                     fileName = decodeURIComponent(matches[1]);
  52.                 }
  53.             }
  54.             a.download = fileName;
  55.             document.body.appendChild(a);
  56.             a.click();
  57.             document.body.removeChild(a);
  58.             URL.revokeObjectURL(downloadUrl);
  59.         } else {
  60.             alert('下载失败,请重试。');
  61.             $('#progressContainer').hide();
  62.             $('#progressText').hide();
  63.         }
  64.     };
  65.     // 发送请求
  66.     xhr.send(form);
  67. });
复制代码
后端代码,利用easyExcel导出
  1. //数据查询
  2. List<Sell> sellList = this.search();
  3. // 将Excel写入ByteArrayOutputStream
  4. try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
  5.     // 使用EasyExcel将数据写入ByteArrayOutputStream
  6.     EasyExcel.write(baos, Sell.class)
  7.             .sheet("列表")
  8.             .doWrite(sellList);
  9.     // 获取Excel字节数组
  10.     byte[] excelBytes = baos.toByteArray();
  11.     // 设置响应头
  12.     response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  13.     response.setCharacterEncoding("utf-8");
  14.     String fileName = URLEncoder.encode("列表导出_Sell", "UTF-8").replaceAll("\\+", "%20");
  15.     response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
  16.     response.setHeader("Cache-Control", "max-age=0");
  17.     response.setContentLength(excelBytes.length); // 设置Content-Length
  18.     // 将Excel字节数组写入响应
  19.     try (OutputStream out = response.getOutputStream()) {
  20.         out.write(excelBytes);
  21.         out.flush();
  22.     }
  23. } catch (IOException e) {
  24.     e.printStackTrace();
  25. }
复制代码
方案2:遮罩层

html代码:
  1. <div id="loadingMask" class="loading-mask" style="display: none;">
  2.     <div class="loading-content">
  3.         <div class="spinner"></div>
  4.         <p>正在导出中...</p>
  5.     </div>
  6. </div>
复制代码
css:
  1. .loading-mask {
  2.     display: none;
  3.     position: fixed;
  4.     top: 0;
  5.     left: 0;
  6.     width: 100%;
  7.     height: 100%;
  8.     background-color: rgba(0, 0, 0, 0.5);
  9.     z-index: 9999;
  10.     display: flex;
  11.     justify-content: center;
  12.     align-items: center;
  13. }
  14. .loading-content {
  15.     text-align: center;
  16.     color: #fff;
  17. }
  18. .spinner {
  19.     border: 8px solid rgba(255, 255, 255, 0.3);
  20.     border-top: 8px solid #fff;
  21.     border-radius: 50%;
  22.     width: 60px;
  23.     height: 60px;
  24.     animation: spin 1s linear infinite;
  25.     margin: 0 auto 20px;
  26. }
  27. @keyframes spin {
  28.     0% { transform: rotate(0deg); }
  29.     100% { transform: rotate(360deg); }
  30. }
  31. button:disabled {
  32.     opacity: 0.6;
  33.     cursor: not-allowed;
  34. }
复制代码
js代码(阻止了有遮罩层时用户仍然可以通过键盘或其他方式触发多次点击):
  1. $(document).ready(function () { // 确保DOM加载完成后执行
  2.     $('#export_btn').on('click', function (e) {
  3.         e.preventDefault(); // 阻止默认表单提交行为
  4.         var $exportBtn = $(this);
  5.         // 禁用导出按钮,防止重复点击
  6.         $exportBtn.prop('disabled', true);
  7.         // 显示遮罩层
  8.         $('#loadingMask').show();
  9.         // 获取表单数据并构建FormData对象
  10.         var formData = $('#searchForm').serializeArray();
  11.         var form = new FormData();
  12.         $.each(formData, function () {
  13.             form.append(this.name, this.value);
  14.         });
  15.         // 添加额外的参数
  16.         form.append('publishFrom', '${RequestParameters.type}');
  17.         // 创建XHR对象
  18.         var xhr = new XMLHttpRequest();
  19.         xhr.open('POST', '路径/exportData', true);
  20.         xhr.responseType = 'blob'; // 设置响应类型为blob
  21.         // 监听下载完成后处理
  22.         xhr.onload = function () {
  23.             $('#loadingMask').hide(); // 隐藏遮罩层
  24.             $exportBtn.prop('disabled', false); // 启用导出按钮
  25.             if (xhr.status === 200) {
  26.                 // 创建下载链接并触发下载
  27.                 var blob = xhr.response;
  28.                 var downloadUrl = URL.createObjectURL(blob);
  29.                 var a = document.createElement('a');
  30.                 a.href = downloadUrl;
  31.                 // 从响应头中获取文件名
  32.                 var disposition = xhr.getResponseHeader('Content-Disposition');
  33.                 var fileName = '下载文件.xlsx';
  34.                 if (disposition && disposition.indexOf("filename*=utf-8''") !== -1) { // 修改:修正单引号字符
  35.                     var filenameRegex = /filename\*=utf-8''(.+)/;
  36.                     var matches = filenameRegex.exec(disposition);
  37.                     if (matches != null && matches[1]) {
  38.                         fileName = decodeURIComponent(matches[1]);
  39.                     }
  40.                 }
  41.                 a.download = fileName;
  42.                 document.body.appendChild(a);
  43.                 a.click();
  44.                 document.body.removeChild(a);
  45.                 URL.revokeObjectURL(downloadUrl);
  46.             } else {
  47.                 alert('下载失败,请重试。');
  48.             }
  49.         };
  50.         // 监听网络错误
  51.         xhr.onerror = function () {
  52.             $('#loadingMask').hide(); // 隐藏遮罩层
  53.             $exportBtn.prop('disabled', false); // 启用导出按钮
  54.             alert('网络错误,请检查您的连接。');
  55.         };
  56.         xhr.send(form);
  57.     });
  58. });
复制代码
后端代码和方案1一致

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81428

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表