java實(shí)現(xiàn)異步導(dǎo)出數(shù)據(jù)
問(wèn)題概述:
使用java作為后臺(tái)語(yǔ)言,用poi導(dǎo)出數(shù)據(jù)時(shí)無(wú)法異步導(dǎo)出,當(dāng)數(shù)據(jù)量稍微大點(diǎn),就會(huì)出現(xiàn)頁(yè)面傻瓜式等待 (點(diǎn)擊導(dǎo)出后,頁(yè)面無(wú)任何反應(yīng)和提示,還以為此功能無(wú)效。然則幾秒后瀏覽器才響應(yīng)。)這樣體驗(yàn)非常 不好。
解決辦法:
很簡(jiǎn)單,將下載數(shù)據(jù)分離為一個(gè)單獨(dú)方法。在觸發(fā)導(dǎo)出后,先獲取并封裝數(shù)據(jù)(數(shù)據(jù)量大的話這個(gè)過(guò)程正好給頁(yè)面做一個(gè)等待框,提示正在下載數(shù)據(jù)),完成后給前臺(tái)返回一個(gè)狀態(tài),當(dāng)前臺(tái)收到返回正確返回狀態(tài)后再關(guān)閉等待框并調(diào)用下載方法。
demo:
1、獲取并封裝數(shù)據(jù)
@RequestMapping("exportExcel") //用戶數(shù)據(jù)導(dǎo)出 public void exportExcel(HttpServletRequest request, HttpServletResponse response) { Map<String,Object> map = new HashMap<String,Object>(); try{ EquipmentAccident search=(EquipmentAccident) request.getSession().getAttribute("equipmentAccident1"); //獲取保存在session中的查詢條件 if(search !=null ){ if(Str.isNotNull(search.getName())){ //名稱 map.put("name", search.getName()); } if(Str.isNotNull(search.getRemark())){ //備注 map.put("remark", search.getRemark()); } } List<User> list=userService.selectExcel(map); //查詢數(shù)據(jù) XSSFWorkbook wb = new XSSFWorkbook(); // 聲明一個(gè)工作薄 XSSFSheet sheet = wb.createSheet("用戶信息"); // 生成一個(gè)表格 Integer columnIndex = 0; sheet.setColumnWidth(columnIndex++, 3 * 512); // 設(shè)置表格第一列寬度為3個(gè)字節(jié) sheet.setColumnWidth(columnIndex++, 10 * 512); //名稱 sheet.setColumnWidth(columnIndex++, 10 * 512); //年齡 sheet.setColumnWidth(columnIndex++, 10 * 512); //備注 // 生成一個(gè)樣式 XSSFCellStyle style1 = wb.createCellStyle(); // 設(shè)置這些樣式 style1.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 生成一個(gè)字體 XSSFFont font1 = wb.createFont(); font1.setFontHeightInPoints((short) 11); font1.setFontName("黑體"); // 字體 // 把字體應(yīng)用到當(dāng)前的樣式 style1.setFont(font1); //在sheet里增加合并單元格 CellRangeAddress cra = new CellRangeAddress(0, 0, 0, 7); sheet.addMergedRegion(cra); int rowInt = 0; //列號(hào) XSSFRow row = sheet.createRow(rowInt++); XSSFCell cell = row.createCell(0); cell.setCellStyle(style1); cell.setCellValue("用戶信息"); int cellInt = 0; row = sheet.createRow(rowInt++); cell = row.createCell(cellInt++); cell.setCellStyle(style1); cell.setCellValue("序號(hào)"); cell = row.createCell(cellInt++); cell.setCellStyle(style1); cell.setCellValue("名稱"); cell = row.createCell(cellInt++); cell.setCellStyle(style1); cell.setCellValue("年齡"); cell = row.createCell(cellInt++); cell.setCellStyle(style1); cell.setCellValue("備注"); int index = 0; if(list!=null && !list.isEmpty()){ for(User obj:list){ index++; cellInt = 0; row = sheet.createRow(rowInt++); cell = row.createCell(cellInt++); cell.setCellValue(index); cell = row.createCell(cellInt++); cell.setCellValue(obj.getName()); cell = row.createCell(cellInt++); cell.setCellValue(obj.getAge()); cell = row.createCell(cellInt++); cell.setCellValue(obj.getRemark()); } } //反饋給前臺(tái)狀態(tài) response.getWriter().append("ok"); //XSSFWorkbook對(duì)象保持到session里,供下載使用 request.getSession().setAttribute("XSSFWorkbook",wb); } catch (Exception e) { e.printStackTrace(); } }
2、分離出來(lái)的下載方法
/** * @param fileName 下載文件名稱 * @param request 請(qǐng)求對(duì)象 * @param response 響應(yīng)對(duì)象 * 2020-11-10 新增 */ @RequestMapping("downloadExcel") public void downloadExcel(String fileName,HttpServletRequest request,HttpServletResponse response) { if(Str.isNotNull(fileName)){ User loginUser = (User) request.getSession().getAttribute("loginUser"); //檢驗(yàn)下載路徑并返回url String url = FileTool.getdownLoadUrl(loginUser, fileName, request); //從url里截取出文件全名 fileName = url.substring(url.lastIndexOf("/")+1); //創(chuàng)建文件輸出流 FileOutputStream fileOut = null; try { fileOut = new FileOutputStream(url); //獲取保存在session中的待下載數(shù)據(jù) XSSFWorkbook wb = (XSSFWorkbook) request.getSession().getAttribute("XSSFWorkbook"); wb.write(fileOut); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } finally{ if(fileOut != null){ try { fileOut.close(); } catch (IOException e) { e.printStackTrace(); } } } try { System.out.println("------------開(kāi)始下載文件---------------"); File file = new File(url); // 以流的形式下載文件。 InputStream fis = new BufferedInputStream(new FileInputStream(url)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); // 清空response response.reset(); // 設(shè)置response的Header response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO8859-1")); response.addHeader("Content-Length", "" + file.length()); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); response.setContentType("application/octet-stream"); toClient.write(buffer); toClient.flush(); toClient.close(); //清除session里的數(shù)據(jù) request.getSession().removeAttribute("XSSFWorkbook"); } catch (IOException ex) { ex.printStackTrace(); } } }
3、前臺(tái)調(diào)用導(dǎo)出數(shù)據(jù)
//導(dǎo)出請(qǐng)求 function exportExcel(){ var load = saveLoad("導(dǎo)出中,請(qǐng)稍后...",1); //打開(kāi)一個(gè)等待框 $.ajax({ type: "post", url: "exportExcel", dataType:"text", error: function(request) { closeSaveLoad(load,1); return false; }, success: function(msg) { if(msg=='ok'){ closeSaveLoad(load,1); //關(guān)閉等待框 //下載請(qǐng)求地址 window.location.href="downloadExcel?fileName=用戶信息" rel="external nofollow" ; }else{ closeSaveLoad(load,1); //關(guān)閉等待框 layer.msg("導(dǎo)出失敗,刷新頁(yè)面重試",{icon:2}); return false; } } }); }
效果如下:
總結(jié):
以前是將封裝數(shù)據(jù)和下載數(shù)據(jù)放一個(gè)方法里面,導(dǎo)致下載需要等待很久,而等待的時(shí)候,無(wú)法提示用戶后臺(tái)正在處理數(shù)據(jù)。將數(shù)據(jù)和下載分開(kāi)后就可以達(dá)到等待時(shí)提示,加載完下載。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
XFire構(gòu)建web service客戶端的五種方式
本篇文章主要介紹了XFire構(gòu)建web service客戶端的五種方式。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01Java中replace、replaceAll和replaceFirst函數(shù)的用法小結(jié)
相信會(huì)java的同學(xué)估計(jì)都用過(guò)replace、replaceAll、replaceFirst這三個(gè)函數(shù),可是,我們真的懂他們嗎?下面通過(guò)這篇文章大家再來(lái)好好學(xué)習(xí)學(xué)習(xí)下這幾個(gè)函數(shù)。2016-09-09Java BigDecimal類的使用和注意事項(xiàng)
這篇文章主要講解Java中BigDecimal類的用法,并簡(jiǎn)單介紹一些注意事項(xiàng),希望能給大家做一個(gè)參考。2016-06-06java定義二維數(shù)組的幾種寫(xiě)法(小結(jié))
下面小編就為大家?guī)?lái)一篇java定義二維數(shù)組的幾種寫(xiě)法(小結(jié))。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10SpringBoot使用freemarker導(dǎo)出word文件方法詳解
這篇文章主要介紹了SpringBoot使用freemarker導(dǎo)出word文件方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-11-11PowerJob的DatabaseMonitorAspect源碼流程
這篇文章主要為大家介紹了PowerJob的DatabaseMonitorAspect源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01java?時(shí)區(qū)時(shí)間轉(zhuǎn)為UTC的實(shí)現(xiàn)
Java提供了多種方式來(lái)實(shí)現(xiàn)時(shí)區(qū)時(shí)間轉(zhuǎn)換為UTC時(shí)間,包括使用java.util.Date和java.util.Calendar以及Java?8中新增的java.time包,下面就來(lái)介紹一下2024-08-08