表格導出功能實踐

表格導出分爲靜態導出與動態導出。javascript

  • 靜態導出是將當前已經渲染的表格項導出爲指定的格式,可爲.xls或.cvs。這種導出無需後端支撐,徹底由前端實現。
  • 動態導出是經過將參數傳與後端接口,該接口負責生成Blob或物理文件,並在Blob或物理文件路徑返回後,由前端進行導出。

準備工做

不管用哪一種方式進行導出,前端都須要準備一下觸發器。 咱們一般使用a標籤的download標籤來實現,十分簡易。html

// 而後經過a標籤的download進行下載
var dispatchDownload = (fileName, href) => {
    var a = document.createElement('a');
    a.addEventListener('click', () => {
        a.download = fileName;
        a.href = href;
    });
    var e = document.createEvent('MouseEvents');
    e.initEvent('click', false, false);
    a.dispatchEvent(e);
};
複製代碼

靜態導出

靜態導出本質上是拼接字符串,只不過特別的是這些字符串符合了.xls, .cvs文件的解析規則。 什麼格式的字符串會被解析爲正確的文件?我在GridManager中前後嘗試了兩種方式。前端

html格式字符串

// 經過當前表格展現數據生成一組相似於下面的html string
var exportHTML = ` <html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head> <body> <table> <thead> <tr> <th>姓名</th> <th>性別</th> <th>年齡</th> </tr> </thead> <tbody> <tr><td>張三</td><td>男</td><td>22</td></tr> <tr><td>李四</td><td>男</td><td>23</td></tr> <tr><td>王五</td><td>女</td><td>24</td></tr> <tr><td>趙六</td><td>女</td><td>22</td></tr> </tbody> </table> </body> </html>`;

var href = `data:application/vnd.ms-excel;base64,${window.btoa(unescape(encodeURIComponent(exportHTML || '')))}`;

// 經過事先聲明的dispatchDownload()函數進行下載
dispatchDownload('花名冊.xls', href);
複製代碼

執行原理

  • 生成table html string
  • 經過btoa轉換爲base64編碼
  • 拼接指定data類型的url
  • 經過a標籤觸發下載

使用這種方式存在導出文件無單元格分割線的問題,因此在GridManager v2.10.5版本中已經將該方式用 以逗號分割的字符串 方式替換。java

以逗號分割的字符串

// 須要經過當前表格展現數據生成一組以逗號分割的字符串。
var exportStr = `姓名,性別,年齡\r\n張三,男,22\r\n李四,男,23\r\n王五,女,24\r\n趙六,女,22`;

// .cvs: data:text/csv, .xls: application/vnd.ms-excel
var href = `data:application/vnd.ms-excel;charset=utf-8,\ufeff${encodeURIComponent(exportStr)}`;

// 經過事先聲明的dispatchDownload()函數進行下載
dispatchDownload('花名冊.xls', href);
複製代碼

執行原理

  • 生成以逗號分割的字符串
  • 經過encodeURIComponent轉義編碼
  • 拼接指定data類型的url
  • 經過a標籤觸發下載

注意: 以上兩種方式都屬於純前端操做,所導出的文件並不是真實文件,在打開時會要求進行來源確認。git

動態導出

動態導出須要後端提供接口,並根據接口返回不一樣的數據進行導出。github

文件路徑

var getHref = () => {
	// 咱們假設如今有一個/download接口,該接口返回了文件地址
	// http.get('/download'); // 僞裝調了下接口
	return 'http://develop.lovejavascript.com/test.xlsx';
};

dispatchDownload('花名冊', getHref());
複製代碼

這種方式對前端來言最爲簡易,只需調用接口並將接口返回的url經過a標籤進行下載便可。 可是使用這種方式,後端須要在服務器上生成真實的文件。 前端是簡單了,但後端不只須要提供文件服務,還須要對生成的文件進行按期清理。 因此,後端小哥通常不會喜歡這種方式。 那麼,後端小哥喜歡什麼? 固然是文件流了。後端

文件流

對於後端返回的文件流,前端使用Blob方式進行導出。在調用後端接口時,須要指定request headers: {responseType: 'blob'}瀏覽器

var getBlog = () => {
	// 咱們假設如今有一個/download接口,該接口返回了文件流
	// http.get('/download', headers: {responseType: 'blob'}); // 僞裝調了下接口
	return blob;
}

// 爲防止返回數據不可用,驗證一下
var blog = getBlog();
if (Object.getPrototypeOf(blob) === Blob.prototype) {
	// 經過URL.createObjectURL()將Blob轉換爲URL。這個新的URL對象表示指定的File對象或Blob對象。
	var url = URL.createObjectURL(blob);

	// 進行下載
	dispatchDownload('花名冊', url);
}
複製代碼

使用這種方式,對於前端來講也沒有什麼工做量。 並且對於後端也無需建立物理文件,僅需生成文件流並將流返回。 在發送請求時所指定的headers: {responseType: 'blob'},僅是告訴瀏覽器前端所指望獲取到的返回格式,對於後端來講無需特殊處理。服務器

最後,推薦一個表格組件GridManagerapp

以上導出的四種方式,能夠到組件源碼進行查看。
相關文章
相關標籤/搜索