Open Closed

ABP Angular proxy responseType for FileStreamResult #2076


User avatar
0
RobWiebkin created
  • ABP Framework version: 4.4.2
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes
  • Exception message and stack trace: NA
  • Steps to reproduce the issue:" NA

I am using the microservice template.

I need to create an endpoint which generates a csv download of data this is stored in our DB. I am using ABP generate proxy, however after the proxy is generated I cannot access the passed data in the front end (it errors in the subscribe). Experimenting with the proxy has shown me that if I edit the proxy to set the responseType to blob, the download works. Unfortunately this change is wiped out every time we regenerate the proxy, and so manually editing it does not seem like a long term viable solution. Is there a way to specify the proxies response type for an endpoint? Or is there a better way of accessing the FileStreamResult in the front end?

Here is the code for the Controller:

[HttpGet]
[Route("entry/export/csv")]
public async Task<IActionResult> GetTimeEntryExportCSV(Guid[] ids)
{
    var bytes = await _fileExportAppService.GetTimeEntryExportCSV(ids);
    MemoryStream stream = new MemoryStream();
    stream.Write(bytes, 0, bytes.Length);
    stream.Position = 0;
    var file = File(stream, "application/octet-stream", "exported-time"+DateTime.Now.ToString("yyyyMMddHHmmss")+".csv");
    return file;    
}

Here is the generated proxy:

getTimeEntryExportCSVByIds = (ids: string[]) =>
    this.restService.request<any, IActionResult>({
      method: 'GET',
      url: '/api/timetracker-service/entry/export/csv',
      params: { ids }
    },
    { apiName: this.apiName });

3 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Please use IRemoteStreamContent

    See https://github.com/abpframework/abp/blob/c86d8406c82ac0281df19374ceb336edfaa661ba/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs#L15-L20

  • User Avatar
    0
    RobWiebkin created

    Please use IRemoteStreamContent

    See https://github.com/abpframework/abp/blob/c86d8406c82ac0281df19374ceb336edfaa661ba/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs#L15-L20

    Hi liangshiwei, I've updated my code using the IRemoteStreamContent (see below), however generated method is still execting to parse the response as JSON unless I manually update the responseType.

    Updated Code:

    [HttpGet]
    [Route("entry/export/csv")]
    public async Task<IRemoteStreamContent> GetTimeEntryExportCSV(Guid[] ids)
    {
        var bytes = await _fileExportAppService.GetTimeEntryExportCSV(ids);
        var memoryStream = new MemoryStream();
        await memoryStream.WriteAsync(bytes);
        memoryStream.Position = 0;
        return new RemoteStreamContent(memoryStream, "exported-time.csv");
    }
    

    Generated proxy:

    getTimeEntryExportCSVByIds = (ids: string[]) =>
        this.restService.request<any, IRemoteStreamContent>({
          method: 'GET',
          url: '/api/timetracker-service/entry/export/csv',
          params: { ids },
        },
        { apiName: this.apiName });
    

    Calling code:

    this.timeTrackerService.getTimeEntryExportCSVByIds(stringOfIds)
          .subscribe(fileResponse => {
            console.group({fileResponse})
            const a = document.createElement('a');
            a.href = URL.createObjectURL(fileResponse);
            a.download = "exported-time" + moment().format("yyyyMMDDHHmmss") + ".csv";
            a.click();
          }, error => { console.log({error}) });
    

    The error is: SyntaxError: Unexpected token P in JSON at position 0 at JSON.parse (<anonymous>) at XMLHttpRequest.o (http://localhost:4200/main.js:1:239492) at e.invokeTask (http://localhost:4200/polyfills.js:1:160868) at Object.onInvokeTask (http://localhost:4200/main.js:1:360127) at e.invokeTask (http://localhost:4200/polyfills.js:1:160789) at t.runTask (http://localhost:4200/polyfills.js:1:155947) at t.invokeTask [as invoke] (http://localhost:4200/polyfills.js:1:162000) at v (http://localhost:4200/polyfills.js:1:174611) at XMLHttpRequest.m (http://localhost:4200/polyfills.js:1:174917)

    With the message: "Http failure during parsing for https://localhost:44325/api/timetracker-service/entry/export/csv?ids=39fff254-296b-4ce2-1498-c4b52e02c0db"

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    you can't use proxy file to download files, It only works for json objects.

    This is the download method code of the file management module, you can refer it:

    downloadFile(file: FileInfo) {
        return this.fileDescriptorService.getDownloadToken(file.id).pipe(
          tap((res) => {
            window.open(
              `${this.apiUrl}/api/file-management/file-descriptor/download/${file.id}?token=${res.token}`,
              '_self'
            );
          })
        );
      }
    
Made with ❤️ on ABP v9.1.0-preview. Updated on December 10, 2024, 06:38