Search code examples
c#angulartypescriptasp.net-coreasp.net-web-api

Downloading an excel file from ASP.net Core API


So our custom API returns:

var result = File(
                new MemoryStream(report, 0, report.Length),
                "application/octet-stream",
                $"missionreport_{DateTime.Now}.xlsx");

return result;

When surfing to the correct API call, it instantly downloads the correct excel file with the corresponding name and styling.

Now we want to do this with an Angular frontend. We created the following:

rapport.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { tap, catchError, map } from 'rxjs/operators';

@Injectable()
export class RapportService {
    private url = "http://localhost:50000/api/report";

    constructor(private http: HttpClient){}

    getMissionReport() {
        return this.http.get(`${this.url}/mission`, {responseType: 'blob'})
                        .pipe(
                                tap(data => console.log('Get mission report: ' + data)),
                                catchError(this.handleError)
                        )
    }

    private handleError(err: HttpErrorResponse) {
        let errorMessage = '';
        if (err.error instanceof ErrorEvent) {
            errorMessage = `An error occurred: ${err.error.message}`;
        } else {
            errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
        }
        console.error(errorMessage);
        return throwError(errorMessage);
    }
}

rapport.component.ts:

getMissionRapport() {
    this.rapportService.getMissionReport().subscribe(response => {
      const blob = new Blob([response], {type: 'application/octet-stream'});
      const url = window.URL.createObjectURL(blob);
      window.open(url);
    })
  }

We linked the function to a button. When clicking on this button we received a 'file' that only showed byte values.


Solution

  • The problem with the code is {type: 'application/octet-stream'}. You aren specifying application/octet-stream in which format you want to save the file. hence you get a stream.

    You have to specify the correct type to download the file as excel, pdf or anything

    application/pdf // for pdf 
    application/vnd.openxmlformats-officedocument.wordprocessingml.document // for Word doc
    application/vnd.openxmlformats-officedocument.spreadsheetml.sheet // for excel