Skip to content

Unable to prompt browser to save file with 'content-disposition: attachment;' #796

Open
@warrenbuckley

Description

@warrenbuckley

Description

Problem

Using the generated client the browser is not prompting the user to auto download the file.

Response Headers

api-supported-versions: 1.0 
 content-disposition: attachment; filename=VideoReport.csv; filename*=UTF-8''VideoReport.csv 
 content-length: 56 
 content-type: text/csv 
 date: Thu,18 Jul 2024 18:40:10 GMT 
 server: Kestrel 

Swagger UI

image

Reproducible example or configuration

Default config just using simple args as a node script

"generate-api": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 openapi-ts --input https://localhost:44344/umbraco/swagger/NewsRoom/swagger.json --output src/api"
import { LitElement, css, html, customElement } from "@umbraco-cms/backoffice/external/lit";
import { UMB_NOTIFICATION_CONTEXT, UmbNotificationContext } from "@umbraco-cms/backoffice/notification";
import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api";
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UUIButtonElement } from "@umbraco-cms/backoffice/external/uui";
import { generateCollectionsReport, generateEventsReport, generateVideoReport } from "../../api";


@customElement('reports-dashboard')
export class ReportsDashboardElement extends UmbElementMixin(LitElement) {

    #notificationContext?: UmbNotificationContext;

    constructor() {
        super();
        this.consumeContext(UMB_NOTIFICATION_CONTEXT, (_instance) => {
            this.#notificationContext = _instance;
        });
    }

    private async _download(reportType: string,  ev: Event){
        
        const buttonElement = ev.target as UUIButtonElement;
        buttonElement.state = "waiting";

        switch(reportType){
            case 'videos':
                await generateVideoReport().then(response => {
                    response
                })
                break;

            case 'events':
                await generateEventsReport();
                break;

            case 'collections':
                await generateCollectionsReport();
                break;
        }

        // Set the state of the clicked button back to sucess
        buttonElement.state = "success";

        // Fire a friendly notification
        this.#notificationContext?.peek("positive", {
            data: {
                headline: "Download Ready",
                message: `Your ${reportType} report is ready for download`
            }
        });
    }

    render() {
        return html`
        <uui-box headline="Newsroom Reporting">
            <p>Here you are able to download CSV reports as required</p>

            <uui-button look="primary" label="Download Videos" @click=${(ev: Event) => this._download('videos', ev)}>
                Download list of all Videos
            </uui-button>

            <uui-button look="primary" label="Download Events"  @click=${(ev: Event) => this._download('events', ev)}>
                Download list of all Events
            </uui-button>

            <uui-button look="primary" label="Download Collections"  @click=${(ev: Event) => this._download('collections', ev)}>
                Download list of all Collections
            </uui-button>

        </uui-box>
    `;
    }

    static styles = [
        UmbTextStyles,
        css`
            :host {
                display: block;
                //padding: var(--uui-box-default-padding);
                padding: 24px;
            }
        `,
    ];
}

export default ReportsDashboardElement;

declare global {
    interface HTMLElementTagNameMap {
        'reports-dashboard': ReportsDashboardElement;
    }
}
// This file is auto-generated by @hey-api/openapi-ts

import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
import type { GenerateCollectionsReportResponse, GenerateEventsReportResponse, GenerateVideoReportResponse } from './types.gen';

/**
 * Generates a simple CSV file and streams it back to the browser.
 * @returns unknown Returns the CSV file stream
 * @throws ApiError
 */
export const generateCollectionsReport = (): CancelablePromise<GenerateCollectionsReportResponse> => { return __request(OpenAPI, {
    method: 'GET',
    url: '/umbraco/newsroom/api/v1/GenerateCollectionsReport',
    errors: {
        401: 'The resource is protected and requires an authentication token'
    }
}); };

/**
 * Generates a simple CSV file and streams it back to the browser.
 * @returns unknown Returns the CSV file stream
 * @throws ApiError
 */
export const generateEventsReport = (): CancelablePromise<GenerateEventsReportResponse> => { return __request(OpenAPI, {
    method: 'GET',
    url: '/umbraco/newsroom/api/v1/GenerateEventsReport',
    errors: {
        401: 'The resource is protected and requires an authentication token'
    }
}); };

/**
 * Generates a simple CSV file and streams it back to the browser.
 * @returns unknown Returns the CSV file stream
 * @throws ApiError
 */
export const generateVideoReport = (): CancelablePromise<GenerateVideoReportResponse> => { return __request(OpenAPI, {
    method: 'GET',
    url: '/umbraco/newsroom/api/v1/GenerateVideoReport',
    errors: {
        401: 'The resource is protected and requires an authentication token'
    }
}); };

OpenAPI specification (optional)

{
    "openapi": "3.0.1",
    "info": {
        "title": "Newsroom Umbraco Backoffice API",
        "contact": {
            "name": "Warren Buckley",
            "url": "https://hackmakedo.com",
            "email": "[email protected]"
        },
        "version": "1.0"
    },
    "paths": {
        "/umbraco/newsroom/api/v1/GenerateCollectionsReport": {
            "get": {
                "tags": [
                    "Report Dashboard"
                ],
                "summary": "Generates a simple CSV file and streams it back to the browser.",
                "responses": {
                    "200": {
                        "description": "Returns the CSV file stream",
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "string",
                                            "format": "binary"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The resource is protected and requires an authentication token"
                    }
                },
                "security": [
                    {
                        "Backoffice User": []
                    }
                ]
            }
        },
        "/umbraco/newsroom/api/v1/GenerateEventsReport": {
            "get": {
                "tags": [
                    "Report Dashboard"
                ],
                "summary": "Generates a simple CSV file and streams it back to the browser.",
                "responses": {
                    "200": {
                        "description": "Returns the CSV file stream",
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "string",
                                            "format": "binary"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The resource is protected and requires an authentication token"
                    }
                },
                "security": [
                    {
                        "Backoffice User": []
                    }
                ]
            }
        },
        "/umbraco/newsroom/api/v1/GenerateVideoReport": {
            "get": {
                "tags": [
                    "Report Dashboard"
                ],
                "summary": "Generates a simple CSV file and streams it back to the browser.",
                "responses": {
                    "200": {
                        "description": "Returns the CSV file stream",
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "type": "string",
                                            "format": "binary"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The resource is protected and requires an authentication token"
                    }
                },
                "security": [
                    {
                        "Backoffice User": []
                    }
                ]
            }
        }
    },
    "components": {
        "securitySchemes": {
            "Backoffice User": {
                "type": "oauth2",
                "description": "Umbraco Authentication",
                "flows": {
                    "authorizationCode": {
                        "authorizationUrl": "/umbraco/management/api/v1/security/back-office/authorize",
                        "tokenUrl": "/umbraco/management/api/v1/security/back-office/token",
                        "scopes": {}
                    }
                }
            }
        }
    }
}

System information (optional)

  • OS: Windows 11
  • Node v20.15.1
  • NPM 10.7.0
  • HeyAPI Version: "@hey-api/openapi-ts": "^0.49.0"

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🔥Something isn't workinghelp wanted 🙋This issue is unlikely to be prioritized, please contribute a pull request if you'd like it resolved

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions