Triggering download of .CSV file in Angular 2 upon user click with authentication

Using a Spring Boot backend, my API utilizes a service to send data through an OutputStreamWriter. In Angular 2, I can trigger a download by clicking on a button:

In Typescript

results(){
    window.location.href='myapicall';
}

In HTML

<button (click)="results()"
    class="btn btn-primary">Export</button>

While this method worked before, implementing security for the API endpoints is causing me to receive a 401 error every time due to missing headers.

I have created a service where I can see the results in the console, but I am struggling to figure out how to actually download the file.

DownloadFileService

import {Injectable} from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/Rx';

@Injectable()
export class DownloadFileService {

    headers:Headers;
    bearer: string;

    constructor(public http: Http) {}

    getFile(url:string) {
        this.bearer = 'Bearer '+ localStorage.getItem('currentUser');
        this.headers = new Headers();
        this.headers.append('Authorization', this.bearer);
        
        return this.http.get(url, {headers: this.headers});
    }

}

I attempted to download the file using a blob as advised in a StackOverflow post: How do I download a file with Angular2

The downloaded file appears as type File with content:

Response with status: 200 OK for URL: my url

However, the data is not actually being downloaded.

downloadFile(data: any){
    var blob = new Blob([data], { type: 'text/csv' });
    var url= window.URL.createObjectURL(blob);
    window.open(url);
}

results(){
    // window.location.href='myapicall';   

     let resultURL =  'myapicall';

    this.downloadfileservice.getFile(resultURL).subscribe(data => this.downloadFile(data)),//console.log(data),
        error => console.log("Error downloading the file."),
        () => console.info("OK");
}

Answer №1

It appears that you simply need to extract the content from the response body:

let parsedResponse = data.text();
this.downloadFile(parsedResponse);

Additionally, I suggest utilizing FileSaver for downloading files since there is no consistent method across browsers even in 2016.

let blob = new Blob([data], { type: 'text/csv' });
saveAs(blob, "data.txt");

For a more detailed explanation, refer to this link

Answer №2

Personally, I also utilize `FileSaver`. When incorporating the extension on the client side, you'll notice that it functions smoothly for `CSV` files. Just be sure to include the extension manually:

FileSaver.saveAs(res, 'export' + extension);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to Implementing OAuth 2.0 in Web Server Environments

Having a basic understanding of HTML, Javascript, and PHP, I found myself needing to incorporate API authorization from another server into my web application. Despite reading the documentation provided by the server, I struggled to determine how to begi ...

Creating a child injector in Angular 2 (version 2.0.0-rc1) through code

Could someone help me with calling the code below using a new injector to dynamically add providers? var componentRef = componentFactory.create( injector, undefined, `#${this.id}` ); I have been searching for an example online on how to create a chil ...

execute field function prior to sorting

Currently, I am building a graphql server in express and using a resolver to modify my fields based on user input from the query. The issue arises from the transformer function returning a function. My goal is to sort the results by a field determined by ...

Attempting to alter the background image through the action of clicking on an image using jQuery, HTML, and CSS

I have created custom weather icons like a sun, cloud, and rainy cloud using Photoshop. My goal is to allow users to click on these icons and change the background image of the website's body. However, despite my efforts, clicking on the images does n ...

The utilization of Angular 2 and the assignment of formControlName values within a

Why must learning Angular2 be such a challenge? <input type="text" formControlName="exposure" type="hidden"> <label>{{exposure}}</label> When I use the formControlName in the input, the value is correct. How can I retrieve the value of ...

The revalidation feature in Next.js' getStaticProps function does not seem to be

https://i.stack.imgur.com/vnNMQ.png I have a question regarding my use of the getStaticProps function in index.js. I am trying to ensure that my API call runs every 60 seconds when a user visits my page, but I am experiencing issues with revalidate not wo ...

Generate Random Quotes - Each new quote should be different from the previous one

As I tackle the FreeCodeCamp 'Random Quote Machine' front end library project using React JSX, everything seemed to be running smoothly except for one major issue - the same quote was often generated two or three times in a row. Obviously, this i ...

Obtain the leaf nodes from a combination of arrays and objects using Lodash

Here is the code structure I want to share with you before explaining my requirements. It displays the input array layout along with the desired outcome: [ { link: "someurl", name: "Foo", subCats: [ { link: "anotherurl", ...

Revamping the User Experience for Amazon Fire TV App

I've been working on creating a 3D application for the Amazon Fire TV using HTML5. I successfully developed and loaded it onto my Fire TV stick using the web app tester tool. Below is snippet of my code: #right{ width: 50%; display: inline-bl ...

Downcasting on "this" is not supported in Typescript

In the example below, the TypeScript compiler does not allow for a direct cast of this to Child. However, it is possible to achieve this using an intermediate variable like 'temp' or double casting as shown in the commented lines. Is this behavio ...

Exploring the Reach and Sequence of AJAX Callbacks

This particular piece of code aims to achieve three main tasks: 1) validate the online status of users, 2) retrieve their information from a slightly different URL, and 3) present both sets of data in HTML format. The implementation appears functional bu ...

Achieving this result in HTML using a jQuery accordion component

Hey there, I'm looking to create a full-height accordion that extends from the bottom to the top of the page, similar to what you see on this website: . I also have a footer positioned below the accordion. The content should load when the page loads ...

Updating a child component in React while applying a filter to the parent component

Although I've come across this question before, I'm struggling to comprehend it within my specific scenario. I'm currently using a search bar to filter the data, which is functioning properly. However, the image is not updating. The URL bei ...

Exploring Vue Routing with Regular Expressions

Recently, I integrated a route with a parameter in my Vue project. const routes = [ { path: "/:lang(^$|^es$|^pt$|^cn$)", name: "Home", component: Page, }, { path: "/privacy", name: "Privacy", component: Privacy, }, { ...

What is the best way to assign the value of a slide range to a PHP variable?

How can I assign the value of a slide range to a PHP variable? I am looking to store the value of a slide range in the variable $amount Click here for an example $(function() { $( "#slider-range-min" ).slider({ range: "min", value: 0 ...

Using Jquery to automatically populate an input field if the user already exists

I'm currently working on populating a form if the user input for name and firstname already exists in my database. However, I am facing an issue with my JavaScript program where it fails to check if the name and firstname combination already exists i ...

What is the method for configuring body attributes in CSS with AngularJS?

Setting the background image of a page using CSS: body { background: url(http://momentumbooks.com.au/wp-content/uploads/2013/06/space.jpg) no-repeat center center fixed; -webkit-background-size: cover; -moz-background-size: cover; -o-backg ...

Use AJAX to send a form submission along with an anchor tag

I've been facing a challenge trying to make this work, but unfortunately, I haven't had any success. Typically, all my forms include a submit input, and I handle AJAX submission in the following manner: <script> $("input#submit").click(fun ...

What is the reason behind TypeScript classifying the argument type from the function as 'never'?

Presented here is the combined type of two signatures for the filter function and the function itself. type Filter = { (arr: string[], f: (item: string) => boolean): string[] (arr: number[], f: (item: number) => boolean): number[] } let filter: ...

Unable to display individual elements of an array using the map function in React Native

Below is my react-native code that I am using to display a list of array elements using the map function. import React from 'react'; import { createStackNavigator } from '@react-navigation/stack'; import {Card} from 'react-native-e ...