Part 1. 前言
好記性不如爛筆頭,本着自己已經在開發過程中花費了大把時間去檢索“為什么不行”以及“該怎么辦”的檢索過程,故在這里進行整理和歸納,也將所參考的文章羅列在Part 0
中,部分解決方式也經過了校驗,方便大家在遇到相同問題時可以方便在茫茫的 cv 博客中找到真正能解決問題的好文(滑稽.jpg
講講我為什么會遇到這個問題,首先業務測使用的文件下載工具采用的是 EasyExcel
,這里放上 EasyExcel
的文檔方便大家檢索使用,我采用的是最簡單的寫的方式,需要明確一點,寫 excel 和 web 端下載 excel 的區別:
Part 2. EasyExcel 寫文件
在最簡單的寫 excel 中,EasyExcel
所需要的條件即文件名/文件路徑、表頭數據、sheet 名以及寫入的數據,以官網示例為例如下:
// WriteTest.java
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
private List<DemoData> data() {
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
// DemoData.java
import lombok.Data;
@Data
public class DemoData {
@ExcelProperty("字符串標題")
private String string;
@ExcelProperty("日期標題")
private Date date;
@ExcelProperty("數字標題")
private Double doubleData;
}
需要注意的是,這里說的是文件名或文件路徑,當 fileName
具體到文件路徑時,excel 文件寫后即寫在該路徑下,若 fileName
為文件名時,會寫在該項目的根目錄下
以上兩種方式的寫 excel ,都並不是 web 端下載的方式(即瀏覽器下載文件的形式)來得到的,這是我最開始誤會的地方
Part 3. EasyExcel web 端寫文件
在實現 web 端的寫文件之前,這里需要先明確一下自己 web 頁面寫文件的方式是哪一種,我這里的業務采用的是 jQuery
的 Ajax 的 Post
請求方式,過程里訪問接口一直都能夠正常訪問,但就是沒有執行 web 端的文件下載,接口返回的盡是些亂碼,於是我就踏上了不斷檢索的道路,很慶幸檢索到和我遇到相同問題的道友,並進一步驗證了他的說法,下面就來談談為什么可以訪問接口但是返回亂碼且不執行 web 端下載的問題:
首先 jQuery
所封裝的 ajax 它所能接收的數據類型需要明確一下,從下圖文檔中可以看到,dataType
在預期的接受類型中,並不包含有二進制流數據 blob
,所以直接通過 $.ajax
的方式是無法滿足預期需求
網上有提供通過更新 xhr
的方式改變 $.ajax
的 responseType
的解決方案,我驗證了下似乎沒有預期效果,因為不接受 blob 類型直接進 error
的回調函數中,報錯信息如下:
DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's '' is '' or 'text' (was 'blob').
這邊也就不再多余的贅述,如果有成功的驗證,歡迎留言指正我的誤解,謝謝大家,下面介紹能夠正常使用的兩種方式
-
通過
form
表單的形式進行提交var url = 'xxxxxxxxxxxx'; var form = document.createElement('form'); var xxx = document.createElement('input'); form.setAttribute('style', 'display:none'); form.setAttribute('target', ''); form.setAttribute('method', 'post'); form.setAttribute('action', url); xxx.type = 'hidden'; xxx.name = 'xxx'; xxx.value = param ? param : ''; form.appendChild(xxx); // ... document.body.appendChild(form); form.appendChild(xxx); // ... form.submit(); form.remove();
-
通過原生
js
實現ajax
的方式,即原生的XMLHttpRequest
對象發出HTTP
請求,對接收的數據先進行createObjectURL
的包裝,再通過以<a>
標簽下載鏈接的方式觸發 web 端下載該文件var params = {xxx:xxx}; var url = 'xxxxxxxxxxxx'; var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); // 也可以使用POST方式,根據接口 xhr.responseType = 'blob'; // 返回類型blob xhr.onload = function () { if (this.status === 200) { var blob = this.response; const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = 'xxx.xlsx'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); } }; // 發送ajax請求 xhr.send(params);
Part 0. Reference
- EasyExcel 使用說明 - 如何使用 EasyExcel
- web頁面實現文件下載的幾種方法 - 闡述 web 端文件下載方式
- EasyExcel實現下載Excel(解決無法從瀏覽器下載問題) - jQuery 的 ajax 無法接收二進制流
- Handle file download from ajax post
- Receiving binary data using JavaScript typed arrays - 二進制文件流
- jQuery.ajax() API 文檔 - ajax API 文檔
- 關於javascript:使用jQuery的ajax方法將圖片檢索為blob
- AJAX 之 XHR, jQuery, Fetch 的對比