Angular 5下载带有发布请求的excel文件

Posted

技术标签:

【中文标题】Angular 5下载带有发布请求的excel文件【英文标题】:Angular 5 download excel file with post request 【发布时间】:2018-08-31 12:40:50 【问题描述】:

我遇到了一个问题,我使用 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 无法打开文件“███████ DASHBOARD (5).xlsx”,因为文件格式或文件扩展名无效。 验证文件没有损坏并且文件扩展名与文件格式匹配。好的

【问题讨论】:

你不需要改变你的http头吗?检查这个:***.com/questions/4212861/… 它应该是什么? requestOptions.headers.append('Content-Type', 'application/msword'); 【参考方案1】:

我整天都在为这个而苦苦挣扎。替换 angular HttpClient 并使用 XMLHttpRequest 如下:

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);

然后在你的downloadFile函数中修改了Blob的创建:

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

在您的情况下,服务将如下所示:

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);
  );

然后是组件:

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();

【讨论】:

这让它在修复后在 Edge 中为我工作,但从 Chrome 下载相同的文件无法修复它。谢谢你让我更近了一步。 :)【参考方案2】:

我设法通过使用 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.');
      );
  

【讨论】:

您先生,至少让我免于在互联网上摸索一个小时以寻求帮助。谢谢。【参考方案3】:

下载使用文件保护程序找到的 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
   ;

【讨论】:

以上是关于Angular 5下载带有发布请求的excel文件的主要内容,如果未能解决你的问题,请参考以下文章

Angular-Spring Boot下载excel文件HttpErrorResponse

markdown 使用Spring Boot和Angular 5下载Excel文件

带有 HttpHeaders 的 Angular 5 JSONP 请求

如何下载 Angular 6 中的 excel 文件

下载 excel 文件的 ajax 请求显示我被截断的响应

下载 excel 文件的 ajax 请求显示我被截断的响应