Как использовать веб-API asp.net core 3.1, возвращающий файл с открытым API-клиентом, сгенерированным кодом для typescript (angular)

это проблема. У меня есть метод веб-API, который создает PDF-файл с использованием DinktoPdf, и я хочу вернуть его угловому клиенту и показать его во всплывающем окне, но, похоже, не могу его открыть. Это код для моего API:

[HttpGet("PrintGravimetricSheetReport")]
[SwaggerOperation(OperationId = "PrintGravimetricSheetReport")]
[SwaggerResponse(200, "Ok", typeof(File))]
[SwaggerResponse(400, "Bad Request", typeof(ErrorResponse))]
public async Task<IActionResult> PrintGravimetricSheetReport()
{
   var vm  = new QuoteLineItemModel();
   var documentContent = await _templateService.RenderTemplateAsync("GravSheet", vm);
   string folderPath = _hostEnvironment.ContentRootPath + "\\GeneratedDocs\\GravSheets\\";

   if (!Directory.Exists(folderPath))
   Directory.CreateDirectory(folderPath);

   var fileName = folderPath + "GravSheet_Report.pdf".AppendTimeStamp();


   var globalSettings = new GlobalSettings
   {
      ColorMode = ColorMode.Color,
      Orientation = Orientation.Portrait,
      PaperSize = PaperKind.A4,
      Margins = new MarginSettings(){Top =10},
      DocumentTitle = "GravSheet Report",
      Out = fileName
   };

   var objectSettings = new ObjectSettings
   {
      PagesCount = true,
      HtmlContent = documentContent,
      WebSettings = { DefaultEncoding = "utf-8" },
      HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true},
      FooterSettings = { FontName = "Arial", FontSize = 9, Line = true, Center = "Report Footer"}
   };

   var pdf = new HtmlToPdfDocument
   {
      GlobalSettings = globalSettings,
      Objects = {objectSettings}
   };

   var file = _converter.Convert(pdf);

   return File(file, "application/pdf");
}

как вы можете заметить, я использую swagger для документирования своего API, а также использую Open-Api для создания клиентской части машинописного текста для углового клиента. это автоматически сгенерированный код:

import { Inject, Injectable, Optional }                      from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
         HttpResponse, HttpEvent, HttpParameterCodec }       from '@angular/common/http';
import { CustomHttpParameterCodec }                          from '../encoder';
import { Observable }                                        from 'rxjs';

import { ErrorResponse } from '../model/errorResponse';

import { BASE_PATH, COLLECTION_FORMATS }                     from '../variables';
import { Configuration }                                     from '../configuration';


@Injectable({
  providedIn: 'root'
})
export class ReportsService {

    protected basePath = 'http://localhost';
    public defaultHeaders = new HttpHeaders();
    public configuration = new Configuration();
    public encoder: HttpParameterCodec;

    constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
        if (configuration) {
            this.configuration = configuration;
        }
        if (typeof this.configuration.basePath !== 'string') {
            if (typeof basePath !== 'string') {
                basePath = this.basePath;
            }
            this.configuration.basePath = basePath;
        }
        this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
    }



    /**
     * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
     * @param reportProgress flag to report request and response progress.
     */
    public printGravimetricSheetReport(observe?: 'body', reportProgress?: boolean): Observable<object>;
    public printGravimetricSheetReport(observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<object>>;
    public printGravimetricSheetReport(observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<object>>;
    public printGravimetricSheetReport(observe: any = 'body', reportProgress: boolean = false ): Observable<any> {

        let headers = this.defaultHeaders;

        // to determine the Accept header
        const httpHeaderAccepts: string[] = [
            'text/plain',
            'application/json',
            'text/json'
        ];
        const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
        if (httpHeaderAcceptSelected !== undefined) {
            headers = headers.set('Accept', httpHeaderAcceptSelected);
        }


        return this.httpClient.get<object>(`${this.configuration.basePath}/api/Reports/PrintGravimetricSheetReport`,
            {
                withCredentials: this.configuration.withCredentials,
                headers: headers,
                observe: observe,
                reportProgress: reportProgress
            }
        );
    }

}

Это то, что я пытался открыть объект, возвращаемый API в клиенте:

printGravSheet(): void {
    this.reportService.printGravimetricSheetReport().subscribe(response => {
      const blob = new Blob([response], { type: 'application/pdf' });
      const url = window.URL.createObjectURL(response);
      const showWindow = window.open(url);
      if (!showWindow || showWindow.closed || typeof showWindow.closed === 'undefined') {
        alert('Please disable your Pop-up blocker and try again');
      }
    });
  }

И просто получить сообщения об ошибках из него. Пожалуйста, может кто-нибудь указать правильный способ сделать это. Заранее спасибо.


person wrabarias    schedule 03.07.2020    source источник


Ответы (1)


Итак, осмотревшись, я обнаружил, что вам нужно удалить строку в веб-API:

Out = fileName

окончательная версия веб-API будет выглядеть так:

[HttpGet("PrintGravimetricSheetReport")]
[SwaggerOperation(OperationId = "PrintGravimetricSheetReport")]
[SwaggerResponse(200, "Ok", typeof(FileContentResult))]
[SwaggerResponse(400, "Bad Request", typeof(ErrorResponse))]
public async Task<IActionResult> PrintGravimetricSheetReport()
{
   var vm  = new QuoteLineItemModel();
   var documentContent = await _templateService.RenderTemplateAsync("GravSheet", vm);
         
   var globalSettings = new GlobalSettings
   {
      ColorMode = ColorMode.Color,
      Orientation = Orientation.Portrait,
      PaperSize = PaperKind.A4,
      Margins = new MarginSettings(){Top =10},
      DocumentTitle = "GravSheet Report",
   };

   var objectSettings = new ObjectSettings
   {
      PagesCount = true,
      HtmlContent = documentContent,
      WebSettings = { DefaultEncoding = "utf-8" },
      HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true},
      FooterSettings = { FontName = "Arial", FontSize = 9, Line = true, Center = "Report Footer"}
  };

  var pdf = new HtmlToPdfDocument
  {
      GlobalSettings = globalSettings,
      Objects = {objectSettings}
  };

  var file = _converter.Convert(pdf);
  return File(file, "application/pdf");
}

и метод компонента в angular:

printGravSheet(): void {
    this.reportService.printGravimetricSheetReport().subscribe((blobResponse: Blob) => {
    const fileUrl = window.URL.createObjectURL(blobResponse);
    const showWindow = window.open(fileUrl);
    if (!showWindow || showWindow.closed || typeof showWindow.closed === 'undefined') {
      alert('Please disable your Pop-up blocker and try again');
    }
  });
};
person wrabarias    schedule 03.07.2020