java實(shí)現(xiàn)異步導(dǎo)出數(shù)據(jù)
問題概述:
使用java作為后臺語言,用poi導(dǎo)出數(shù)據(jù)時無法異步導(dǎo)出,當(dāng)數(shù)據(jù)量稍微大點(diǎn),就會出現(xiàn)頁面傻瓜式等待 (點(diǎn)擊導(dǎo)出后,頁面無任何反應(yīng)和提示,還以為此功能無效。然則幾秒后瀏覽器才響應(yīng)。)這樣體驗(yàn)非常 不好。
解決辦法:
很簡單,將下載數(shù)據(jù)分離為一個單獨(dú)方法。在觸發(fā)導(dǎo)出后,先獲取并封裝數(shù)據(jù)(數(shù)據(jù)量大的話這個過程正好給頁面做一個等待框,提示正在下載數(shù)據(jù)),完成后給前臺返回一個狀態(tài),當(dāng)前臺收到返回正確返回狀態(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(); // 聲明一個工作薄 XSSFSheet sheet = wb.createSheet("用戶信息"); // 生成一個表格 Integer columnIndex = 0; sheet.setColumnWidth(columnIndex++, 3 * 512); // 設(shè)置表格第一列寬度為3個字節(jié) sheet.setColumnWidth(columnIndex++, 10 * 512); //名稱 sheet.setColumnWidth(columnIndex++, 10 * 512); //年齡 sheet.setColumnWidth(columnIndex++, 10 * 512); //備注 // 生成一個樣式 XSSFCellStyle style1 = wb.createCellStyle(); // 設(shè)置這些樣式 style1.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 生成一個字體 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; //列號 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()); } } //反饋給前臺狀態(tài) response.getWriter().append("ok"); //XSSFWorkbook對象保持到session里,供下載使用 request.getSession().setAttribute("XSSFWorkbook",wb); } catch (Exception e) { e.printStackTrace(); } }
2、分離出來的下載方法
/** * @param fileName 下載文件名稱 * @param request 請求對象 * @param response 響應(yīng)對象 * 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("------------開始下載文件---------------"); 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、前臺調(diào)用導(dǎo)出數(shù)據(jù)
//導(dǎo)出請求 function exportExcel(){ var load = saveLoad("導(dǎo)出中,請稍后...",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); //關(guān)閉等待框 //下載請求地址 window.location.href="downloadExcel?fileName=用戶信息" rel="external nofollow" ; }else{ closeSaveLoad(load,1); //關(guān)閉等待框 layer.msg("導(dǎo)出失敗,刷新頁面重試",{icon:2}); return false; } } }); }
效果如下:
總結(jié):
以前是將封裝數(shù)據(jù)和下載數(shù)據(jù)放一個方法里面,導(dǎo)致下載需要等待很久,而等待的時候,無法提示用戶后臺正在處理數(shù)據(jù)。將數(shù)據(jù)和下載分開后就可以達(dá)到等待時提示,加載完下載。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
XFire構(gòu)建web service客戶端的五種方式
本篇文章主要介紹了XFire構(gòu)建web service客戶端的五種方式。具有很好的參考價值,下面跟著小編一起來看下吧2017-01-01Java中replace、replaceAll和replaceFirst函數(shù)的用法小結(jié)
相信會java的同學(xué)估計都用過replace、replaceAll、replaceFirst這三個函數(shù),可是,我們真的懂他們嗎?下面通過這篇文章大家再來好好學(xué)習(xí)學(xué)習(xí)下這幾個函數(shù)。2016-09-09Java BigDecimal類的使用和注意事項(xiàng)
這篇文章主要講解Java中BigDecimal類的用法,并簡單介紹一些注意事項(xiàng),希望能給大家做一個參考。2016-06-06SpringBoot使用freemarker導(dǎo)出word文件方法詳解
這篇文章主要介紹了SpringBoot使用freemarker導(dǎo)出word文件方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11PowerJob的DatabaseMonitorAspect源碼流程
這篇文章主要為大家介紹了PowerJob的DatabaseMonitorAspect源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01java?時區(qū)時間轉(zhuǎn)為UTC的實(shí)現(xiàn)
Java提供了多種方式來實(shí)現(xiàn)時區(qū)時間轉(zhuǎn)換為UTC時間,包括使用java.util.Date和java.util.Calendar以及Java?8中新增的java.time包,下面就來介紹一下2024-08-08