0%

Angular 筆記 - 下載功能開發

download

這次記錄一下用 Angular 開發的下載檔案功能,流程是這樣:

操作流程

  • 從 API 渲染按鈕,並且點擊後會得到該按鈕的 key 與 value。
  • 出現列表。
  • 點擊列表後會接收到該列表的檔名。
  • 把列表的檔名去呼叫下載檔案的 API。
  • 產生下載檔案。

實作過程

建立下載的方法

http.service.ts

下載檔案要傳三個參數:

  • url: api 的連結,是一個字串。
  • body: post API 時,request 的參數,會是一個物件。
  • option: blob 的物件。

其中最重要的就是這一行:

1
let option = { responseType: "blob" as "json" };

因為是用 Angular 的 HttpClient 透過瀏覽器下載檔案,所以需要先指定回傳的型別(responseType)為 Blob 格式。

因為 HttpClient 預設回傳的格式為 json,要轉成 Blob 格式才能下載。

因為這次傳案要下載的是 PDF 檔案,電腦並無法直接下載 PDF,所以要轉成 Blob 格式,並把 option 物件在呼叫時放在第三個參數用。

1
2
3
4
5
6
7
8
9
10
download<T>(paramUrl: string, paramBody: object, paramOption?: object): Observable<T> {
let option = { responseType: "blob" as "json" };
return this._http.post<T>(paramUrl, paramBody, option).pipe(
catchError((err) => {
if (err instanceof HttpErrorResponse) {
return throwError(this.error(err));
}
})
);
}

download.service.ts

專案中另外建一個給下載檔案專用的 service,因為下載檔案的觀察者物件的型態無法預期,所以使用 any 型別,可以接受任意的型別。

1
2
3
fileDownload(param: fileDownload): Observable<any> {
return this._http.download<any>(`${environment.apiUrl}/File/DownloadFile`, param);
}

download.component.ts

  • 建立一個 download 函式作為按鈕點擊事件用。
  • 帶入要傳的參數 this.fileName
  • 呼叫 API。
  • 給一個區域變數,型別為 Blob,並產生新的 Blob 物件,把回傳的 res 資料放在第一個參數,並用一個大括號接收,原因是之前已經轉成 json 格式,後面的參數要放一個物件裡面是 type,其值為要下載的檔案格式。
  • 定義一個 downloadUrl,要去產生一個 createObjectURL 的靜態方法。MDN 解釋,再把剛剛產生的 blob 物件放在這個方法內。
  • 並且動態產生一個 a 連結。
  • 定義連結的 hrefdownloadURL 這個物件。
  • 使用 a 連結的 download 屬性,並將下載檔名用 api 給個參數名稱。
  • 並增加一個 click 點擊事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
download() {
let req: fileDownload = {
FILENM: this.fileName,
};

this._fileDownload.fileDownload(req).subscribe((res) => {
let blob: Blob = new Blob([res], { type: "application/pdf" });
let downloadUrl = window.URL.createObjectURL(blob);
let link = document.createElement("a");
link.href = downloadUrl;
link.download = this.fileName;
link.click();
});
}

如此,就完成了一個下載檔案的功能。

參考資料