Angular2 download excel file from Web API, file is corrupt

前端 未结 4 686
猫巷女王i
猫巷女王i 2020-12-20 03:05

I am trying to download a file that I created with ClosedXML. I have verified that the file is not corrupt but, for some reason, it works just with Angular1, not Angular2.

相关标签:
4条回答
  • 2020-12-20 03:18

    I know that others have found the same problem. I have resolved it, but had to switch to xhr to make it work.

    This first method is the one that does NOT work. I simplified it somewhat from above:

        generateMonthlySpreadsheet2(searchCriteria: Object) {
            let headers = new Headers();
            headers.append('Content-Type', 'application/json');
            headers.append('responseType', 'blob');
    
            return this._http.post(`${AppSettings.REPORTS_API_URL}/Report/MonthlySpreadsheet`, {headers: headers})
                .map(response => {
                    if (response.status == 400) {
                        this.handleError;
                    } else if (response.status == 200) {
                        var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                        var blob = new Blob([(<any>response)._body], { type: contentType });            // size is 89KB instead of 52KB
    //                    var blob = new Blob([(<any>response).arrayBuffer()], { type: contentType });  // size is 98KB instead of 52KB
    //                    var blob = new Blob([(<any>response).blob()], { type: contentType });         // received Error: The request body isn't either a blob or an array buffer
                        return blob;
                    }
                })
                .catch(this.handleError);
        }
    

    This second method is the one that DOES work:

    generateMonthlySpreadsheet(searchCriteria: Object): Observable<Object[]> {
        return Observable.create(observer => {
    
            let xhr = new XMLHttpRequest();
    
            xhr.open('POST', `${AppSettings.REPORTS_API_URL}/Report/MonthlySpreadsheet`, true);
            xhr.setRequestHeader('Content-type', 'application/json');
            xhr.responseType='blob';
    
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
    
                        var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                        var blob = new Blob([xhr.response], { type: contentType });
                        observer.next(blob);
                        observer.complete();
                    } else {
                        observer.error(xhr.response);
                    }
                }
            }
            xhr.send();
    
        });
    }
    

    Hopefully this will help others! I saw this issue posted elsewhere so I will add a link to my solution there as well.

    -- Karen

    0 讨论(0)
  • 2020-12-20 03:21

    This is what worked for me(make sure that service indeed sends back xlsx file as response):

    1. Install these dependencies for show "save file" pop-up

      npm install file-saver --save-dev
      npm install @types/file-saver --save-dev
      
    2. Import in your service:

      import * as FileSaver from 'file-saver';
      
    3. Usage:

      downloadFile(): void {
          let url: string = “http://yourdomain.com/exports/excelExport.aspx”;
         let headers = new Headers({ 'Content-Type': 'application/json'} );
      
          //in case you have custom headers, else you can ignore this part
      headers.set('x-custom-header1', “some value”);
          headers.set('x-custom-header2', “some value2”);
      
          let options = new RequestOptions({responseType: ResponseContentType.Blob, headers });
      
          this.http.get(url, options)
              .map(res => res.blob())
              .subscribe(
              data => {
      FileSaver.saveAs(data, 'Export.xlsx'); 
              },
              err => {
                  console.log('error');
                  console.error(err);
              });
      }
      
    0 讨论(0)
  • 2020-12-20 03:25
    Latest solution Try If using Angular 5:
    
    ///angular side
    
    //header
    let expheaders = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    let options = new RequestOptions({ headers: expheaders, responseType: ResponseContentType.Blob });
    
    
    this.http.post(this.modeleffectiveperiodserviceurl+"ExportToXlsx",JSON.stringify({
                               modeleffectiveperioddetails:model,
                               colheader:columns
                               }),options)
                               .subscribe(data => { 
                                 var blob = new Blob([data.blob()], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
                                 var url= window.URL.createObjectURL(blob);
                                 window.open(url);                   
                              });
    
    
    
    //////////server side
    
    
      byte[] bytes = this._exportmanager.GetExcelFromServer(modeleffectivepc, colheader);
                HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
                httpResponseMessage.Content = new ByteArrayContent(bytes.ToArray());
                httpResponseMessage.Content.Headers.Add("x-filename", fileName);
                httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
                httpResponseMessage.StatusCode = HttpStatusCode.OK;
                return httpResponseMessage;
    
    please tell if any problem
    
    0 讨论(0)
  • 2020-12-20 03:30

    this is the solution I used to Dwobnload the complete file with style (colors..)

    The WebApi:

     [HttpGet]
            [Route("api/RapproResult/DownloadExcelReport/{reportName}")]
            public HttpResponseMessage DownloadExcelReport( string reportName)
            {
    
    
                try
                {
                     string filePath = HttpContext.Current.Server.MapPath("~/Report/Report_TEST.XLS");
    
                    if (!string.IsNullOrEmpty(filePath ))
                    {
    
    
                        using (MemoryStream ms = new MemoryStream())
                        {
                            using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                            {
                                byte[] bytes = new byte[file.Length];
                                file.Read(bytes, 0, (int)file.Length);
                                ms.Write(bytes, 0, (int)file.Length);
    
                                HttpResponseMessage httpResponseMessage = new HttpResponseMessage(); 
                                httpResponseMessage.Content = new ByteArrayContent(ms.GetBuffer());
                                httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                                httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    
                                httpResponseMessage.StatusCode = HttpStatusCode.OK;
                                return httpResponseMessage;
                            }
                        }
                    }
                    return this.Request.CreateResponse(HttpStatusCode.NotFound, "File not found.");
                }
                catch (Exception ex)
                {
                    return   this.Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
                }
    
    
            }
    

    this is the angular service :

     protected downloadExcelReportService( reportName: string) {
    
            let completeUrl = this.downloadExcelReportUrl+reportName;
            return Observable.create(observer => {
                let xhr = new XMLHttpRequest();
    
                xhr.open('GET', completeUrl, true);
                xhr.setRequestHeader('Content-type', 'application/json');
                xhr.responseType='blob';
    
                xhr.onreadystatechange = function () {
                  if (xhr.readyState === 4) {
                    if (xhr.status === 200) { 
                        debugger;
                      var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                      var blob = new Blob([xhr.response], { type: contentType });
                      observer.next(blob);
                      observer.complete();
                      return observer;
    
                    } else {
                      observer.error(xhr.response);
                    }
                  }
                }
                debugger;
                xhr.send();
              });
        }
    

    And finally the Angular component method using FileSaver Api

    import * as FileSaver from "file-saver";
    
    
    
     downloadexcelReport(data)
          { 
              this._servive.downloadExcelReport(data.RapproName)
              .subscribe(
                _data =>  FileSaver.saveAs(_data, data.RapproName+".xls" ) ), 
                error => console.log("Error downloading the file."),
                () => console.log('Completed file download.');  
          }
    

    I hope that helps you.

    0 讨论(0)
提交回复
热议问题