首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 匯出 Excel 實戰:POI、非同步下載、按鈕防重、Cookie 輪詢完整方案

     編輯:Java 相關知識

專案需求

  • 符合條件:正常匯出,彈出下載對話框,匯出期間禁用按鈕,完成後啟用。
  • 不符合條件:提示使用者不可匯出,保留查詢條件不跳轉頁面。

踩坑歷程與解決方案

1. AJAX 非同步請求無法觸發瀏覽器下載

原因:AJAX 使用字元流交換,瀏覽器不識別為檔案下載。同步 AJAX 也無效。

2. Form Submit 刷新頁面導致查詢條件遺失

改用隱藏 iframe 作為表單 target,後端若驗證失敗以串流方式回傳錯誤訊息,前端在 iframe onload 解析處理,避免頁面跳轉。

3. 匯出完成後無法通知前端啟用按鈕

Response OutputStream 已用於傳送 Excel 二進位資料,無法再傳回 JSON 旗標。
解法:後端匯出完成後寫入一個短效 Cookie(如 updtstatus=1),前端 setInterval 輪詢 document.cookie,偵測到即清除 Cookie、清除計時器、啟用按鈕。

前端核心程式碼

<button id="detailEp" onclick="return exportCheck(true);">匯出</button>

<script>
let timer;
$("#myForm").submit(function() {
    $("button[type=submit]", this).attr("disabled", "disabled");
    timer = setInterval(checkExportDone, 1000);
});

function checkExportDone() {
    if (getCookie("updtstatus") === "1") {
        clearInterval(timer);
        $("#detailEp").removeAttr("disabled");
        deleteCookie("updtstatus");
    }
}
function getCookie(name) { /* 解析 document.cookie 回傳值 */ }
function deleteCookie(name) { /* 設定過期時間刪除 */ }
</script>

後端 POI 匯出 + Cookie 回寫

public void buildExcelDocument(Map<String, Object> data, String fileName,
                               HttpServletRequest req, HttpServletResponse resp) throws Exception {
    HSSFWorkbook wb = new HSSFWorkbook();
    // ... 建立 Sheet、寫入標題、資料列(略) ...

    // 設定下載標頭
    String encodedName = ChineseUtil.encodeFilename(fileName + ".xls", req);
    resp.setContentType("application/vnd.ms-excel;charset=UTF-8");
    resp.setHeader("Content-Disposition", "attachment;filename=" + encodedName);

    try (OutputStream os = resp.getOutputStream()) {
        wb.write(os);
        os.flush();
    }

    // 關鍵:寫入 Cookie 通知前端匯出完成
    Cookie ck = new Cookie("updtstatus", "1");
    ck.setMaxAge(3600);
    ck.setPath("/");
    resp.addCookie(ck);
}

反思與改進方向

  • Cookie + 輪詢屬 Hack 手法,現代專案建議採用:
    - fetch + blob + URL.createObjectURL() 純前端下載(後端回傳二進位)。
    - WebSocket / SSE 伺服器推播完成事件。
    - 獨立下載 API:匯出請求回傳下載 Token,前端輪詢 Token 狀態,完成後 location.href = /download?token=xxx。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved