需求:页面点击导出,先按照页面条件去数据库查询,然后将查询到的数据导出。
问题:由于查询特别耗时,所以点击之后页面会看上去没有反应,就在点击之后在页面增加了一个进度条,等待后盾查询结束之后,导出时,进度条会显示导出进度,导出结束之后进度条会消失。效果如下:
注意点:后端需要在响应头中设置ContentLength,前端需要用这个更新进度
response.setContentLength(excelBytes.length); // 设置Content-Length
html代码:
<button type="button" id="export_btn" class="layui-btn btn_blue">导 出</button>
<!-- 进度条容器 --> <div id="progressContainer" style="display:none; margin-top:20px;"> <div id="progressBar"></div> </div> <!-- 显示下载进度百分比 --> <div id="progressText" style="display:none; margin-top:5px;">下载进度: 0%</div>
css:
#progressContainer { width: 100%; background-color: #f3f3f3; border: 1px solid #ccc; border-radius: 5px; } #progressBar { width: 0%; height: 20px; background-color: #4caf50; border-radius: 5px; }
js代码:
// 进度条 $('#export_btn').on('click', function () { // 获取表单数据 var formData = $('#searchForm').serializeArray(); var params = {}; $.each(formData, function () { params[this.name] = this.value; }); params['publishFrom'] = '${RequestParameters.type}'; // 构建查询字符串 var queryString = $.param(params); // 创建XHR对象 var xhr = new XMLHttpRequest(); xhr.open('POST', '路径/exportData', true); xhr.responseType = 'blob'; // 设置响应类型为blob // 显示进度条 $('#progressContainer').show(); $('#progressText').show(); $('#progressBar').css('width', '0%'); $('#progressText').text('下载进度: 0%'); // 设置请求头以模拟表单提交 // xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 监听下载进度 xhr.onprogress = function (event) { if (event.lengthComputable) { var percentComplete = Math.round((event.loaded / event.total) * 100); console.log('Loaded:', event.loaded, 'Total:', event.total); $('#progressBar').css('width', percentComplete + '%'); $('#progressText').text('下载进度: ' + percentComplete + '%'); } else { console.log('无法计算进度'); } }; // 下载完成后处理 xhr.onload = function () { if (xhr.status === 200) { // 隐藏进度条 $('#progressContainer').hide(); $('#progressText').hide(); // 创建下载链接并触发下载 var blob = xhr.response; var downloadUrl = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = downloadUrl; // 从响应头中获取文件名 var disposition = xhr.getResponseHeader('Content-Disposition'); var fileName = '下载文件.xlsx'; if (disposition && disposition.indexOf('filename*=utf-8\'\'') !== -1) { var filenameRegex = /filename\*=utf-8''(.+)/; var matches = filenameRegex.exec(disposition); if (matches != null && matches[1]) { fileName = decodeURIComponent(matches[1]); } } a.download = fileName; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(downloadUrl); } else { alert('下载失败,请重试。'); $('#progressContainer').hide(); $('#progressText').hide(); } }; // 发送请求 xhr.send(queryString); });
后端代码,使用easyExcel导出
//数据查询 List<Sell> sellList = this.search(); // 将Excel写入ByteArrayOutputStream try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // 使用EasyExcel将数据写入ByteArrayOutputStream EasyExcel.write(baos, Sell.class) .sheet("列表") .doWrite(sellList); // 获取Excel字节数组 byte[] excelBytes = baos.toByteArray(); // 设置响应头 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("列表导出_Sell", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); response.setHeader("Cache-Control", "max-age=0"); response.setContentLength(excelBytes.length); // 设置Content-Length // 将Excel字节数组写入响应 try (OutputStream out = response.getOutputStream()) { out.write(excelBytes); out.flush(); } } catch (IOException e) { e.printStackTrace(); }
标签:进度条,easyExcel,导出,event,xhr,数据量,var,response From: https://blog.csdn.net/weixin_42285408/article/details/142363872