4

Can any one please give an example of fetching application/octet-stream response from angular 6 httpClient. I am using the below code and it doesn't work ( I get unknown error - 401 response) -

import { saveAs } from 'file-saver';

getJobOutput() {
    this.workflowService.fetchOutput(this.jobId,this.outputId).subscribe((response : any) => { // download file
              var blob = new Blob([response.blob()], {type: 'application/octet-stream'});
    var filename = 'file.csv';
    saveAs(blob, filename);
    });
   }

Service is as below -

 fetchOutput(jobId : string, outputId) {
    var jobOutputURL = "myEnpoint";
     var params = this.createHttpAuthorization(jobOutputURL,"GET");
     params["format"] = "csv";
    const options = {
            headers: new HttpHeaders( { 'Content-Type': 'application/octet-stream',
                                        'Accept' : 'application/octet-stream',
                                        'Access-Control-Allow-Origin' : '*'}
                                    )};

    var endpoint = `${jobOutputURL}?oauth_consumer_key=${params["oauth_consumer_key"]}&oauth_signature_method=${params["oauth_signature_method"]}&oauth_nonce=${params["oauth_nonce"]}&oauth_timestamp=${params["oauth_timestamp"]}&oauth_version=1.0&format=${params["format"]}&oauth_signature=${params["oauth_signature"]}`;
return this.httpClient.get(endpoint, {...options, responseType: 'blob'});
  }
4
  • Your request looks fine, if you are getting 401 the you are not authorized to download the the .csv. Check your API, is your access allowed. Commented Mar 18, 2019 at 12:17
  • 401 error means "Unauthorized". Are you sure you authorized the request? Commented Mar 18, 2019 at 12:17
  • Yes, it is. The same request when asked in jquery works fine. Commented Mar 18, 2019 at 12:18
  • This request works - this.getOutputFileURL = function(jobId, outputId, format) { var type = "GET", url = this.apiLocation + "/jobs/" + jobId + "/output/" + outputId + "/", params = buildOauthParams(this.apiKey); $.extend(params, {format: format || "Raw"}); var signature = generateSignature(type, url, params, this.apiSecret); $.extend(params, {oauth_signature: signature}); window.location.assign(url + "?" + $.param(params)); }; Commented Mar 18, 2019 at 12:20

2 Answers 2

9

To fetch an application/octet-stream, you have to set arraybuffer as the response type in the Angular HttpHeaders.

This is the service method:

fetchOutput(): Observable<ArrayBuffer> {
    let headers = new HttpHeaders();

    const options: {
        headers?: HttpHeaders;
        observe?: 'body';
        params?: HttpParams;
        reportProgress?: boolean;
        responseType: 'arraybuffer';
        withCredentials?: boolean;
    } = {
        responseType: 'arraybuffer'
    };

    return this.httpClient
        .get('https://your-service-url.com/api/v1/your-resource', options)
        .pipe(
            map((file: ArrayBuffer) => {
                return file;
            })
        );
}

This is the call to the service method and to the saveAs function:

this.yourService
    .fetchOutput()
    .subscribe((data: any) => {
        const blob = new Blob([data], { type: 'application/octet-stream' });
        const fileName = 'Your File Name.csv';
        saveAs(blob, fileName);
    })

As other users are suggestion: 401 Unauthorized is usually a client side error due to missing credentials.

Sign up to request clarification or add additional context in comments.

10 Comments

Hi Julien,Thank you for the code above. I still a GET request with 401 (Unauthorized) error. However, the same URL when I paste on postman, gives me the correct response. I doubt this is authorization issue as I am able to access other types of API's that are hosted on the same server.
Do you use windows authentication, or what kind of authorization? Tools like postman can implicitly set authorization, whilst Angular cannot.
I am using oauth 1.0 and setting these params - oauth_consumer_key, oauth_signature_method: HMAC-SHA1 oauth_nonce, oauth_timestamp, oauth_version: 1.0 Also, other GET requests work with these oauth 1.0 parameters (via my angular 6 application). oauth_signature: VTat UuyYG5bWrpSZ18lJfFeUjQ=
Try one of the following: Compare the url that Angular produces via the chrome developer network tab with the one that postman creates. Double check the headers, that Angular sets, and compare them with the one postman creates. Try debugging the authorization method in your backend to check, whether the pararams, that you define in Angular, reach your endpoint correctly.
@Aetherix Yes, in the above case the map operator is not required, though I added it to indicate, that you could alter the output of the observable
|
0

This works for me:

this.httpClient.get(endpoint, {...options, responseType: 'text'}).subscribe((data: any) => {
    const a = document.createElement("a");
    a.href = "data:text/csv," + data;
    let filename = "CSVDownload";
    a.setAttribute("download", filename + ".csv");
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
},
(error) => {
    console.log('error', error);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.