Angular 6 - 从httpClient获取CSV响应

3

请问有没有人能够给出从angular 6 httpClient获取application/octet-stream响应的示例。我使用了下面的代码,但它不起作用(我得到未知错误 - 401响应) -

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);
    });
   }

以下是服务内容:

服务如下 -

 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'});
  }

您的请求看起来没问题,如果您收到了 401 错误,则表示您未被授权下载 .csv 文件。请检查您的 API,确认您是否被允许访问。 - Ashish Ranjan
401错误意味着“未经授权”。您确定已经授权该请求了吗? - Harun Yilmaz
是的,没错。当使用 jQuery 时,相同的请求可以正常工作。 - kadambari narotra
这个请求有效 - 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)); }; - kadambari narotra
2个回答

8

要获取application/octet-stream,您需要在Angular HttpHeaders中将响应类型设置为arraybuffer

这是服务方法:

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;
            })
        );
}

这是对服务方法和saveAs函数的调用:

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

正如其他用户所建议的那样:401未经授权通常是由于缺少凭据而导致的客户端错误。


尝试以下操作之一:将Angular通过Chrome开发者网络选项卡生成的URL与Postman创建的进行比较。仔细检查Angular设置的标头,并将其与Postman创建的进行比较。尝试调试后端授权方法,以检查您在Angular中定义的参数是否正确到达您的端点。 - Julien Ambos
谢谢Julien。我有另一个应用程序也在Jquery中成功运行,我看到两个不同之处-在jquery中,请求头中的Host为"server domain",而我的angular应用程序在请求头中的origin为"http://localhost:4200"。您知道这是否会有影响吗? - kadambari narotra
根据OAuth 1.0规范,这不应该有任何区别。在第10章的oauth页面上列出了401代码可能出现的错误列表(https://oauth.net/core/1.0/):无效的消费者密钥,无效/过期的令牌,无效的签名或无效/已使用的nonce。 - Julien Ambos
“pipe(map(…))”是用来做什么的?好像没有这个额外步骤也能工作。 - Aetherix
1
@Aetherix 是的,在上述情况下,map操作符是不必要的,尽管我添加它是为了表明您可以更改可观察对象的输出。 - Julien Ambos
显示剩余4条评论

0
这对我来说很有效:
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);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接