Angular 5下载带有帖子请求的excel文件

时间:2018-03-22 07:06:47

标签: angular angular-services

我遇到了一个问题,我用Angular 1下载了一个Excel文件,但如果我在Angular 5中实现了相同的代码,则会显示文件已损坏的错误。我的回复是 ArrayBuffer ,我无法读取该文件。

以下是我的代码:

服务

 DownloadData(model:requiredParams):Observable<any>{
  const headers = new Headers();
  const requestOptions = new RequestOptions({ headers: headers });
  requestOptions.headers.append('Content-Type', 'application/json');

   const body = JSON.stringify(model);
  return this.http.post(url, body, requestOptions)
  .map((res:any) => res)
 .catch((e: any) => Observable.throw(this.errorHandler(e)));
 }

组件:

exportToExcel() {
    this.loadingOverlayFlag = true;
   this.podashboardService.DownloadData(this.data).subscribe(result=>{
    console.log(result);
    this.downloadFile(result._body,'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'export.xlsx');
  })
  }

 downloadFile(blob: any, type: string, filename: string) {

 var binaryData = [];
   binaryData.push(blob);

     const url = window.URL.createObjectURL(new Blob(binaryData, {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})); // <-- 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();

   }

我可以下载该文件,但无法阅读其内容。错误是:

  

Microsoft Excel
  Excel无法打开文件&#39;███████DASHBOARD(5).xlsx&#39;因为文件格式或文件扩展名无效。   验证文件是否已损坏,以及文件扩展名是否与文件格式匹配。行

3 个答案:

答案 0 :(得分:6)

I struggle with this one all day. Replace angular HttpClient and use XMLHttpRequest as follows:

var oReq = new XMLHttpRequest();
  oReq.open("POST", url, true);
  oReq.setRequestHeader("content-type", "application/json");
  oReq.responseType = "arraybuffer";

  oReq.onload = function (oEvent) {
    var arrayBuffer = oReq.response;
    if (arrayBuffer) {
      var byteArray = new Uint8Array(arrayBuffer);
      console.log(byteArray, byteArray.length);
      this.downloadFile(byteArray, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'export.xlsx');
    }
  };

  oReq.send(body);

Then modified the creation of the Blob in your downloadFile function:

const url = window.URL.createObjectURL(new Blob([binaryData]));

In your case the service will look something like this:

DownloadData(model:requiredParams):Observable<any>{
  return new Observable(obs => {
    var oReq = new XMLHttpRequest();
    oReq.open("POST", url, true);
    oReq.setRequestHeader("content-type", "application/json");
    oReq.responseType = "arraybuffer";

    oReq.onload = function (oEvent) {
      var arrayBuffer = oReq.response;
      var byteArray = new Uint8Array(arrayBuffer);
      obs.next(byteArray);
    };

    const body = JSON.stringify(model);
    oReq.send(body);
  });
}

Then the component:

exportToExcel() {
  this.loadingOverlayFlag = true;
  this.podashboardService.DownloadData(this.data).subscribe(result=>{
    // console.log(result);
    this.downloadFile(result,'application/vnd.openxmlformats-
    officedocument.spreadsheetml.sheet', 'export.xlsx');
  })
}

downloadFile(blob: any, type: string, filename: string) {

  var binaryData = [];
  binaryData.push(blob);

  const url = window.URL.createObjectURL(new Blob(binaryData, { type: filetype })); // <-- 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();
}

答案 1 :(得分:4)

我设法通过使用httpClient使其正常工作(httpOptions中的responseType: 'arraybuffer'完成了技巧)。

createReportBackend() {

    const httpOption: Object = {
      observe: 'response',
      headers: new HttpHeaders({
        'Content-Type': 'application/json'
      }),
      responseType: 'arraybuffer'
    };

    this.httpClient.post('http://localhost:8080/api/report', this.data, httpOption)
      .pipe(map((res: HttpResponse) => {
        return {
          filename: 'Drinks.xlsx',
          data: new Blob(
            [res['body']],
            { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}
          ),
        };
      }))
      .subscribe(res => {
        if (window.navigator.msSaveOrOpenBlob) {
          window.navigator.msSaveBlob(res.data, res.filename);
        } else {
          const link = window.URL.createObjectURL(res.data);
          const a = document.createElement('a');
          document.body.appendChild(a);
          a.setAttribute('style', 'display: none');
          a.href = link;
          a.download = res.filename;
          a.click();
          window.URL.revokeObjectURL(link);
          a.remove();
        }
      }, error => {
        throw error;
      }, () => {
        console.log('Completed file download.');
      });
  }

答案 2 :(得分:0)

下载使用文件保护程序找到的exel文件的最简单方法是:

//Declaration
headers: HttpHeaders;
options: any;

 //Constructor or u can have for specific method
 this.headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    this.options = {
        observe: 'response',
        headers: this.headers,
        responseType: 'arraybuffer'
    };

 //Service request:
  this.httpClient.post('http://localhost:8080/api/report', this.data, this.option)
  .pipe(
  catchError(err => this.handleError(err))
    ).subscribe(response => {
        Helper.exportExelFile(response, 'FileName');
    });

//component or in helper function in one class

import * as FileSaver from 'file-saver';
 function exportExelFile(data, filename) {
const blobValue = new Blob([data['body']], {
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
 FileSaver.saveAs(blobValue, filename + '.' + FileType.EXCEL);
}

export const Helper = {
  exportExelFile
   };
相关问题