[Angular] 取得後端檔案並顯示錯誤訊息

[Angular] 取得後端檔案並顯示錯誤訊息

後端取得檔案後轉成FileStream丟到前端,如有錯誤時,則回傳BadRequest及錯誤訊息

[HttpGet]
public IActionResult GetFile()
{
  string err = "";
  try 
  {
    FileStream file = new FileStream("filepath", FileMode.Open, FileAccess.Read);
    if (file == null)
        return BadRequest("查無檔案");
        
    return new FileStreamResult(file, "application/vnd.ms-word");
  }
  catch (Exception excp)
  {
      err = excp.Message;
  }
  return BadRequest(err);
}

前端接收檔案:

this.http.get(`Api/GetFile`, {
  responseType: 'blob', //預設為json,改為blob
  observe: 'response',
}).pipe(
  map((res: any) => {
    let blob = null;
    if (res && res.body) {
      blob = new Blob([res.body], { type: 'application/vnd.ms-word' });
    }
    return blob;
  }),
  catchError(err => this.handleBlobError(err)) //處理錯誤訊息
).subscribe(
  blob => {...} //收到檔案後續處理
);

從Chrome開發者工具可以看出,當回傳BadRequest為文字時,實際上會回傳一個含文字的blob在error中,如下圖:

所以可用以下方式取出錯誤訊息:

private async handleBlobError(err) {
  if (err instanceof HttpErrorResponse && err.error instanceof Blob &&
    (err.error.type === "application/json" || err.error.type === "text/plain")) {
    return new Promise<any>((resolve, reject) => {
      let reader = new FileReader();
      reader.onload = (e: Event) => {
        try {
          const errmsg = err.error.type === "application/json" ?
            JSON.parse((<any>e.target).result) : (<any>e.target).result; //也可以回傳json物件
          reject(new HttpErrorResponse({
            error: errmsg,
            headers: err.headers,
            status: err.status,
            statusText: err.statusText,
            url: err.url
          }));
        } catch (e) {
          reject(err);
        }
      };
      reader.onerror = (e) => {
        reject(err);
      };
      reader.readAsText(err.error);
    });
  }
  return new Promise<any>((resolve, reject) => {
    reject(err);
  });
}

如此就可以在回傳錯誤時,顯示訊息:

this.http.get(
  ...
).pipe(
  map(...),
  catchError(err => this.handleBlobError(err)) //處理錯誤訊息
).subscribe(
  blob => {...}, //收到檔案後續處理
  error => {
    console.log(error);
    alert(JSON.stringify(error)); //顯示錯誤訊息
  }
);

參考資料

https://stackoverflow.com/questions/49479959/angular-5-manage-http-get-with-blob-response-and-json-errors