首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Spring MVC 文件下載:瀏覽器直接訪問 URL 正常,AJAX 按鈕點擊無反應?

     編輯:程式設計綜合問答

核心差異:瀏覽器原生導航 vs AJAX 請求

場景瀏覽器行為關鍵點
地址欄輸入 URL / <a href>發起 **導航請求**,收到 Content-Disposition: attachment 直接彈出「另存為」對話框瀏覽器原生處理下載流
JS $.ajax / fetch / Angular $http發起 **XHR/Fetch 請求**,響應體進入 JS 變量,**不會自動觸發下載**需手動創建 Blob + ObjectURL + 點擊隱藏 <a>

為什麼 AJAX 不彈下載框?

瀏覽器安全策略:腳本發起的請求不允許直接彈出文件保存對話框,必須由用戶交互(點擊 <a download>)觸發。

正確方案:AJAX 獲取 Blob → 前端觸發下載

// Controller 返回 byte[] 或 ResponseEntity<byte[]>
@GetMapping("/download/{id}")
public ResponseEntity<byte[]> download(@PathVariable String id) {
    byte[] data = fileService.getFileBytes(id);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    headers.setContentDispositionFormData("attachment", "export.xlsx");
    return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
// 前端 AngularJS / jQuery / 原生 fetch 統一模式
function downloadFile(url, filename) {
    fetch(url, { method: 'GET', credentials: 'include' })
        .then(resp => resp.blob())
        .then(blob => {
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            a.remove();
            window.URL.revokeObjectURL(url);
        });
}

// 按鈕綁定
<button ng-click="downloadFile('/api/download/123', 'report.xlsx')">下載</button>

若必須用 window.open / <a href> 但帶參數?

// 構建帶參數 URL,瀏覽器原生導航自動下載
const params = new URLSearchParams({ token: getToken(), id: 123 });
window.open(`/api/download?${params}`, '_blank');
// 或隱藏 form 提交
const form = document.createElement('form');
form.method = 'GET';
form.action = '/api/download';
form.target = '_blank';
Object.entries({ token: getToken(), id: 123 }).forEach(([k,v]) => {
    const i = document.createElement('input');
    i.type = 'hidden'; i.name = k; i.value = v;
    form.appendChild(i);
});
document.body.appendChild(form);
form.submit();
form.remove();

調試利器:Fiddler / Chrome DevTools Network

  1. 觀察響應 Header:Content-Disposition: attachment; filename="..." 是否存在
  2. 響應體:是否為二進制流(非 JSON/HTML 錯誤頁)
  3. 狀態碼:200 vs 401/403/500

總結

AJAX 無法直接下載文件。選項二擇一:

  1. 改用 window.open / 隱藏 form.submit() 觸發瀏覽器原生導航下載
  2. 堅持 AJAX:後端返回 Blob,前端 createObjectURL + <a download>.click() 模擬下載

推薦方案 2,體驗更可控(進度條、錯誤提示、不阻塞頁面)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved