解決辦法
原生開發
當原生開發的時候,就要依靠操作XMLHttpRequest對象來獲取響應的二進制流。經過百度我發現雖然這個對象沒有提供直接獲取流的屬性,但是它的文檔中responseType是可以返回一個Blob對象的。而Blob對象就是一個二進制數據的對象,只要我們獲取到這個對象,就可以通過瀏覽器獲取到需要的excel文件。
代碼:
$('.exportBtn').bind("click", function () { var method = 'post';//請求方法 var url = 'http://localhost.....';//請求url var xhr = new XMLHttpRequest();//定義一個XMLHttpRequest對象 xhr.open(method, url, true); xhr.responseType = 'blob';//設置ajax的響應類型為blob xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); xhr.onload = function ()//當請求完成,響應就緒進入 { if (this.status == 200)//當響應狀態碼為200時進入 { var blob = this.response;//獲取響應返回的blob對象 //這一段用來判斷是否是IE瀏覽器,因為下面有些代碼不支持IE if (typeof window.navigator.msSaveBlob !== 'undefined') { window.navigator.msSaveBlob(blob, "NPI_PROJECT.xlsx"); return; } var a = document.createElement('a');//在dom樹上創建一個a標簽 var url = window.URL.createObjectURL(blob);//我的理解是生成一個相對於瀏覽器的虛擬url,用於指向傳入的blob對象,讓瀏覽器可以通過這個url找到這個blob對象 a.href = url;//將url賦值給a標簽的href屬性 a.download = 'NPI_PROJECT.xlsx';//設置設置下載文件的名稱 a.click();//主動觸發a標簽點擊事件 } }; xhr.send(JSON.stringify({ name: '', status: '' }));//附帶參數發送請求 });
jquery插件開發 -->jquery.fileDownload githiub地址
$('.exportBtn').bind("click", function () { var httpMethod = 'post'; var url = "http://localhost....."; var params = { name: '', status: '' }; $.fileDownload(url, { httpMethod: httpMethod, // 因為這個插件貌似只支持URL參數,所以要用jquery param將js對象轉成URL參數 data: $.param(params), prepareCallback: function (url) { console.log("正在導出..."); }, //要想成功回調失敗和成功方法,要在響應首部加 response.setHeader("Set-Cookie", "fileDownload=true; path=/"); successCallback: function (url) { console.log("導出成功"); }, failCallback: function (html, url) { console.log("導出失敗"); } })
后台代碼:
action:
public void exportExcel(){ String tankfarmIdStr = null; if(tankfarmId > 0){ tankfarmIdStr = Long.toString(tankfarmId); }else{ IDMmOrderMap orderMap = (IDMmOrderMap) ResourceFactory.getInstance().getBeanFromContext("dMmOrderMap"); tankfarmIdStr = orderMap.getTankfarmIds(this.getLoginUser()); } IMmExcelRptMap rptMap = (IMmExcelRptMap) ResourceFactory.getInstance().getMapFromContext("mmExcelRptMap"); byte[] content = rptMap.exportVDImBalance(matlId, startDate, endDate, tankfarmIdStr); OutputStream os = null; try { os = this.getServletResponse().getOutputStream(); this.getServletResponse().setContentType("application/vnd.ms-excel"); this.getServletResponse().setHeader("Content-disposition", "attachment; filename=" + "balance_monthly.xls"); os.write(content); } catch (IOException e) { e.printStackTrace(); } finally { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } }
map:
public byte[] exportVDImBalance(Long matlId, String startDate, String endDate, String tankfarmIdStr) { IDImBalanceMap map = (IDImBalanceMap) ResourceFactory.getInstance().getMapFromContext("dImBalanceMap"); List<Map<String, Object>> datas = map.findVBalanByMatlAndTime(matlId, startDate, endDate, null, tankfarmIdStr); //獲取數據 IJExcelReportMap rptMap = new JExcelReportMap(); byte[] content = rptMap.exportReport(new File(this.getFilePath(IM_BALANCE_MONTHLY)), datas, null); return content; }
public byte[] exportReport(File template, Collection datas, Map params) { byte[] content = null; if (template != null && template.exists()) { Workbook wb = null; WritableWorkbook wwb = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { try { wb = Workbook.getWorkbook(template); WorkbookSettings settings = new WorkbookSettings (); settings.setWriteAccess(null); wwb = Workbook.createWorkbook(bos, wb); WritableSheet[] sheets = wwb.getSheets(); for (int i = 0; i < sheets.length; i ++){ this.fillSheet(sheets[i], datas, params); } wwb.write(); } catch (Exception e) { throw new InteriorException("", e); } finally { try { wwb.close(); } catch (WriteException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } wb.close(); } content = bos.toByteArray(); }finally { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } return content; }
protected void fillSheet(WritableSheet sheet, Collection datas, Map params) throws RowsExceededException, WriteException{ int row = sheet.getRows(); int column = sheet.getColumns(); int beginRow = -1; int beginCol = -1; List<WritableCell> cellFields = new ArrayList<WritableCell>(); Map<WritableCell, Boolean> groupMap = new HashMap<WritableCell, Boolean>(); //行 for (int i = 0; i < row; i ++) { //列 for (int j = 0; j < column; j ++){ //根據列,行獲取到單元格 WritableCell cell = sheet.getWritableCell(j, i); //獲取到單元格值 String cellExp = cell.getContents(); //判斷單元格內是否有標簽 if (cellExp != null && cellExp.length() > 0){ //如果有$F{標志 if (cellExp.indexOf("$F{") >= 0) { if (beginRow == -1){ beginRow = i; } if (beginCol == -1) { beginCol = j; } if (i > beginRow) break; cellFields.add(cell); if (this.isGroup(cellExp)) { groupMap.put(cell, Boolean.TRUE); } sheet.addCell(this.fillCell(cell, null, cell.getCellFormat())); //表頭,副標 } else { Object value = this.fillCellByExp(cellExp, params, datas); sheet.addCell(this.fillCell(cell, value, cell.getCellFormat())); } } } } this.fillDatas(datas, params, sheet, cellFields, groupMap, beginRow, beginCol); }
Excel模板: