1. 程式人生 > 程式設計 >java實現非同步匯出資料

java實現非同步匯出資料

問題概述:

使用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;
    }
   }
  });
 }

效果如下:

java實現非同步匯出資料

總結:

以前是將封裝資料和下載資料放一個方法裡面,導致下載需要等待很久,而等待的時候,無法提示使用者後臺正在處理資料。將資料和下載分開後就可以達到等待時提示,載入完下載。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。