Angular 4.3:使用新的HttpClient获取数组缓冲区

8

我想切换到新的HttpClient。 到目前为止,我是按照以下方式处理文件下载:

getXlsx (): Observable<any> {
    return this.http.get('api/xlsx', {
      responseType: ResponseContentType.ArrayBuffer, // set as ArrayBuffer instead of Json
    })
    .map(res => downloadFile(res, 'application/xlsx', 'export.xlsx'))
    .catch(err => handleError(err));
  }

export function downloadFile(data: any, type: string, filename: string): string {
  const blob = new Blob([data._body], { type });
  const url = window.URL.createObjectURL(blob);

  // create hidden dom element (so it works in all browsers)
  const a = document.createElement('a');
  a.setAttribute('style', 'display:none;');
  document.body.appendChild(a);

  // create file, attach to hidden element and open hidden element
  a.href = url;
  a.download = filename;
  a.click();
  return url;
}

将 responseType 改为 'arraybuffer' 会导致空文件。有什么解决办法吗?


2
你有没有尝试过使用responseType: 'blob'并且去掉new Blob()的方式? - Martin Adámek
非常感谢!这个程序正常运行了! - Luke
2个回答

12

所以Martin解决了我的问题:

getXlsx (): Observable<any> {
    return this.http.get('api/xlsx', {
      responseType: 'blob' // <-- changed to blob
    })
    .map(res => downloadFile(res, 'application/xlsx', 'export.xlsx'))
    .catch(err => handleError(err));
  }

export function downloadFile(blob: any, type: string, filename: string): string {
  const url = window.URL.createObjectURL(blob); // <-- work with blob directly

  // create hidden dom element (so it works in all browsers)
  const a = document.createElement('a');
  a.setAttribute('style', 'display:none;');
  document.body.appendChild(a);

  // create file, attach to hidden element and open hidden element
  a.href = url;
  a.download = filename;
  a.click();
  return url;
}

5
上述方法可以解决问题,但是只是在DOM中添加锚定标签并模拟点击,似乎有些不太规范。我们最近在Angular 5网站中遇到了类似的问题,需要下载文档,使用了FileSaver(https://www.npmjs.com/package/file-saver)库更加优雅。 通过使用npm install file-saver命令安装FileSaver,并进行相关导入,你可以使用以下代码来下载文件:
getDocument(document: Document) {
    let headers = new HttpHeaders(); // additional headers in here

    return this._http.get(url, {
        headers: headers,
        responseType: "blob" // this line being the important part from the previous answer (thanks for that BTW Martin) 
    }).map(
        res => {
            var x = res;
            if (res) {
                let filename = documentName;
                saveAs(x, filename);
            }
            return true;
        },
        err => {
            return true;
        }
    );
} 

如果本地存在saveAs命令,则使用该命令,否则实现一些其他逻辑来复制其功能。这个操作在底层可能会做类似的事情(我不确定,因为没有机会查看),但它将其分隔在易于使用的第三方软件包中,我希望这个软件包能够得到维护(祈祷),而无需我更新功能以适应不同软件包/浏览器的新版本。

基本上,file-saver 看起来做的事情是一样的,但它还添加了许多跨浏览器检查和回退,以覆盖众多边缘情况。https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js - Drenai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接