Angular Excel 導入與導出

前言

本文基於 angular v7.2.7,初次編寫於2019-4-17。前端

雖然代碼是基於angular 7.2.7,可是語法是基於 angular 4.X 以上都可使用。在項目開發過程當中,咱們常常須要跟後端進行文件交互,常見的諸如 圖片上傳,excel 導入與導出等。這裏咱們只討論關於excel 的導入與導出。npm


Excel 導入

excel 導入在angular 中其實很是簡單,只須要安裝 xlsx插件 就能夠了。json

  • 安裝 xlsx 插件

npm install xlsx --save後端

  • 在component 中導入

import * as XLSX from 'xlsx';跨域

  • 關鍵代碼
import * as XLSX from 'xlsx';

excelData = [];

importExcel(evt: any) {
    /* wire up file reader */
    const target: DataTransfer = <DataTransfer>(evt.target);
    if (target.files.length !== 1) throw new Error('Cannot use multiple files');
    const reader: FileReader = new FileReader();
    reader.onload = (e: any) => {
      /* read workbook */
      const bstr: string = e.target.result;
      const wb: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' });

      /* grab first sheet */
      const wsname: string = wb.SheetNames[0];
      const ws: XLSX.WorkSheet = wb.Sheets[wsname];

      /* save data */
      this.excelData = (XLSX.utils.sheet_to_json(ws, { header: 1 }));

      evt.target.value = "" // 清空
    };
    reader.readAsBinaryString(target.files[0]);

  }複製代碼


Excel 導出

傳統的導出功能咱們通常是放在後端實現,由後端生成文件的Url或者文件流給到前端。注:這種是經過瀏覽器的下載功能直接下載的。通常有如下幾種方式實現:瀏覽器

  • get 請求 + window.open(url)

後端返回一個 文件的url 或者 文件流,這種方式都可以直接下載。前提是http請求爲getbash

  • post 請求 + <a>標籤

前端代碼:app

exportExcel(codeList: string[]) {
    return this.http.post(this.ExportExcelByCodesUrl, codeList, {
      responseType: 'arraybuffer',//設置響應類型
      observe:"response",//返回response header
      headers: { 'Content-Type': 'application/json' }
    })
      .subscribe((response:any)=>{
        this.downLoadFile(response, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8")
      })

  }

 /**
   * Method is use to download file.
   * @param data - Array Buffer data
   * @param type - type of the document.
 */
downLoadFile(data: any, type: string) {
     var blob = new Blob([data.body], { type: type});
     let downloadElement = document.createElement('a');
     let href = window.URL.createObjectURL(blob); //建立下載的連接
     downloadElement.href = href;
     let filename = data.headers.get("Download-FileName");//後端返回的自定義header
     downloadElement.download = decodeURI(filename); 

     document.body.appendChild(downloadElement);
     downloadElement.click(); //點擊下載
     document.body.removeChild(downloadElement); //下載完成移除元素
     window.URL.revokeObjectURL(href); //釋放掉blob對象
  }複製代碼

後端代碼:post

這裏後端是使用的Asp.Net Core 2.1 ui

public IActionResult CreateExcel(string fileName,List<ExportProductModel> list)
 {
   string[] propertyNames = {""};//業務代碼
   string[] propertyNameCn = {""};//業務代碼
   MemoryStream ms = ExcelsHelper<ExportProductModel>.ListToExcel(fileName, list, propertyNames, propertyNameCn);
   HttpContext.Response.Headers.Add("Download-FileName",WebUtility.UrlEncode(fileName));
   return File(ms, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;", WebUtility.UrlEncode(fileName));
 }

services.AddCors(options =>
                 {
                   options.AddPolicy("AllowAllOrigin", builder =>
                                     {
                                       builder.AllowAnyHeader()
                                         .AllowAnyMethod()
                                         .AllowAnyOrigin()
                                         .AllowCredentials()
                                         .WithExposedHeaders("Download-FileName"); 

                                     });
                 });複製代碼

後端代碼這裏關鍵點是須要設置跨域的響應頭(也就是「Download-FileName」),具體每一個語言有本身的實現方式。若是不設置的話,前端沒法獲取響應頭。

  • post 請求 + form 表單 + iframe 標籤(暫無代碼實現)


總結

我在開發過程當中有遇到如下幾個問題,折騰了好久:

  • 先後端的MIME類型沒有對應,致使文件沒法成功下載,這裏是 完整的MIME類型列表
  • 沒法獲取response header,緣由有二:

(1)後端沒有設置跨域的響應頭

(2)前端的http請求 語法書寫錯誤,一直獲取到的是http response body,而非完整的http response。完整寫法參考以上代碼,關鍵是 : observe:"response"


最後,但願這篇文章可以幫助到你,共勉!

相關文章
相關標籤/搜索