1. 程式人生 > >獲取jqGrid中的所有資料匯出並生成Excel檔案流供使用者下載(post請求實現檔案下載)

獲取jqGrid中的所有資料匯出並生成Excel檔案流供使用者下載(post請求實現檔案下載)

最近有一個需求是:

將jqGrid表格中的資料生成報表Excel檔案返回給使用者。

我的想法是獲取jqGrid中的資料然後生成json資料,傳給後端,生成檔案流,響應到前端,儲存為excel檔案。

ajax為什麼不能夠實現下載檔案

ajax的返回值型別是json,text,html,xml型別,或者可以說ajax的接收型別只能是string字串,不是流型別,所以無法實現檔案下載。

但用ajax仍然可以獲得檔案的內容,該檔案將被保留在記憶體中,無法將檔案儲存到磁碟。這是因為JavaScript無法和磁碟進行互動,否則這會是一個嚴重的安全問題,js無法呼叫到瀏覽器的下載處理機制和程式,會被瀏覽器阻塞。

並且 我用ajax實現的時候出現了很多bug。

在網上參考好多部落格,經過不斷的除錯,我還是選擇了原生的XMLHttpRequest物件進行post請求。

blob(HTML5 新特性)

二進位制大物件,是一個可以儲存二進位制檔案的容器。

作用

Js一直以來都沒有比較好的可以直接處理二進位制的方法。而Blob的存在,允許我們可以通過JS直接操作二進位制資料。

Blob物件可以看做是存放二進位制資料的容器,此外還可以通過Blob設定二進位制資料的MIME型別。

BLOB是一個大檔案,典型的BLOB是一張圖片或一個聲音檔案,由於它們的尺寸,必須使用特殊的方式來處理(例如:上傳、下載或者存放到一個數據庫)。

重點應用
  • 目前做的通過URL下載檔案。
  • 分片上傳檔案(將大檔案分片,輪詢向後臺提交各檔案片段)。

後端程式碼

/**
 * 生成Excel報表
 * Error:存在問題
 * 1. 前端表格中沒有Student物件的一些屬性,生成報表時不必要顯示的屬性欄位在Excel中顯示。
 *    solve:加判斷控制。
 * 2. (由於blob是HTML5新出的)相容性問題:chrome、firefox、opera無問題,
 * 3. 檢測grid表格中有無欄位名稱衝突問題。
 *    solve:細心檢查即可
 * 4. 下載完Excel,打開出現"檔案已損壞 無法開啟"問題,這是因為office受保護試圖導致(安全問題)
 *    solve:在office選項裡邊修改一下即可(客戶端問題)
 * @param list
 * @param response
 */
@RequestMapping(value = "/exstudent",consumes = "application/json;charset=utf-8") public void export (@RequestBody List<Student> list, HttpServletResponse response){ OutputStream out = null; String name = "學生資訊管理表"; for (Student stu:list) { System.out.println(stu.getStudentname()); } try { response.setHeader("content-type", "application/octet-stream"); response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=" +URLEncoder.encode(name, "UTF-8")+".xlsx"); out = response.getOutputStream(); //呼叫老師自己寫的庫,本篇文章不詳細說生成Excel檔案的事情。 TExcel.exportExcel(name,Student.class,list,out); System.out.println("下載ok"); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); }finally{ } }

前端程式碼:

//匯出按鈕被點選之後,將按鈕製為無效(防止多次生成)
function abideBtn(){
    console.log("禁止按鈕......");
    $("#download").attr({"href":"#"});
    $("#download").css("cursor","not-allowed");
}
//下載過程中出錯誤,
function downloadError(){
    console.log("發生錯誤,下載失敗");
    alert("下載中出現錯誤!請重試");
    $("#download").attr({"href":"javascript:exportData();"});
    $("#download").css("cursor","pointer");
}
//匯出表格資料
//注意:下面獲取jqGrid中所有行資料的前提是分頁在前端,而不是後端。
//如果你是在後端分頁,那麼你會發現,你會將所有資料都顯示出來。
function exportData() {
    var grid = jQuery("#grid");
    //獲取當前顯示的資料
    var rowNum = grid.jqGrid('getGridParam', 'rowNum'); //獲取顯示配置記錄數量
    var total = grid.jqGrid('getGridParam', 'records'); //獲取查詢得到的總記錄數量
    //設定rowNum為總記錄數量並且重新整理jqGrid,使所有記錄現出來呼叫getRowData方法才能獲取到所有資料
    grid.jqGrid('setGridParam',{rowNum: total,}).trigger('reloadGrid');
    var rows = o.jqGrid('getRowData');
    grid.jqGrid('setGridParam',{rowNum: rowNum,}).trigger('reloadGrid');
    postToPOM(rows);
}
//傳送post請求
function postToPOM(rows) {
    console.log(rows);
    var url = "../student/exstudent";
    var xhr = new XMLHttpRequest();
    xhr.open('POST',url,true);
    xhr.responseType = "blob";
    xhr.setRequestHeader("Content-Type"
        , "application/json;charset=utf-8");
    //新增監聽事件。
    xhr.addEventListener("load",abideBtn,false);
    xhr.addEventListener("error",downloadError,false);
    xhr.onload = function (){
        if(this.status === 200){
            //建立Bolb物件
            var blob = this.response;//html5新出的
            var reader = new FileReader();
            reader.readAsDataURL(blob);
            reader.onload = function(e){
                //建立a標籤,構造下載彈窗
                var a = document.createElement("a");
                a.id = "downloadTag";
                a.download = '學生資訊管理表.xlsx';
                a.href = e.target.result;
                $("body").append(a);
                a.click();
                $("#downloadTag").remove();
                console.log("下載完成!");
                //恢復按鈕
                $("#download").attr({"href":"javascript:exportData();"});
                $("#download").css("cursor","pointer");
            }
        }
    };
    xhr.send(JSON.stringify(rows));
}