java實現非同步匯出資料
阿新 • • 發佈:2020-11-26
問題概述:
使用java作為後臺語言,用poi匯出資料時無法非同步匯出,當資料量稍微大點,就會出現頁面傻瓜式等待 (點選匯出後,頁面無任何反應和提示,還以為此功能無效。然則幾秒後瀏覽器才響應。)這樣體驗非常 不好。
解決辦法:
很簡單,將下載資料分離為一個單獨方法。在觸發匯出後,先獲取並封裝資料(資料量大的話這個過程正好給頁面做一個等待框,提示正在下載資料),完成後給前臺返回一個狀態,當前臺收到返回正確返回狀態後再關閉等待框並呼叫下載方法。
demo:
1、獲取並封裝資料
@RequestMapping("exportExcel") //使用者資料匯出 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); //查詢資料 XSSFWorkbook wb = new XSSFWorkbook(); // 宣告一個工作薄 XSSFSheet sheet = wb.createSheet("使用者資訊"); // 生成一個表格 Integer columnIndex = 0; sheet.setColumnWidth(columnIndex++,3 * 512); // 設定表格第一列寬度為3個位元組 sheet.setColumnWidth(columnIndex++,10 * 512); //名稱 sheet.setColumnWidth(columnIndex++,10 * 512); //年齡 sheet.setColumnWidth(columnIndex++,10 * 512); //備註 // 生成一個樣式 XSSFCellStyle style1 = wb.createCellStyle(); // 設定這些樣式 style1.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 生成一個字型 XSSFFont font1 = wb.createFont(); font1.setFontHeightInPoints((short) 11); font1.setFontName("黑體"); // 字型 // 把字型應用到當前的樣式 style1.setFont(font1); //在sheet裡增加合併單元格 CellRangeAddress cra = new CellRangeAddress(0,7); sheet.addMergedRegion(cra); int rowInt = 0; //列號 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("序號"); 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()); } } //反饋給前臺狀態 response.getWriter().append("ok"); //XSSFWorkbook物件保持到session裡,供下載使用 request.getSession().setAttribute("XSSFWorkbook",wb); } catch (Exception e) { e.printStackTrace(); } }
2、分離出來的下載方法
/** * @param fileName 下載檔名稱 * @param request 請求物件 * @param response 響應物件 * 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"); //檢驗下載路徑並返回url String url = FileTool.getdownLoadUrl(loginUser,fileName,request); //從url裡截取出檔案全名 fileName = url.substring(url.lastIndexOf("/")+1); //建立檔案輸出流 FileOutputStream fileOut = null; try { fileOut = new FileOutputStream(url); //獲取儲存在session中的待下載資料 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("------------開始下載檔案---------------"); 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(); // 設定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裡的資料 request.getSession().removeAttribute("XSSFWorkbook"); } catch (IOException ex) { ex.printStackTrace(); } } }
3、前臺呼叫匯出資料
//匯出請求 function exportExcel(){ var load = saveLoad("匯出中,請稍後...",1); //開啟一個等待框 $.ajax({ type: "post",url: "exportExcel",dataType:"text",error: function(request) { closeSaveLoad(load,1); return false; },success: function(msg) { if(msg=='ok'){ closeSaveLoad(load,1); //關閉等待框 //下載請求地址 window.location.href="downloadExcel?fileName=使用者資訊" rel="external nofollow" ; }else{ closeSaveLoad(load,1); //關閉等待框 layer.msg("匯出失敗,重新整理頁面重試",{icon:2}); return false; } } }); }
效果如下:
總結:
以前是將封裝資料和下載資料放一個方法裡面,導致下載需要等待很久,而等待的時候,無法提示使用者後臺正在處理資料。將資料和下載分開後就可以達到等待時提示,載入完下載。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。