Angular - 使用 HttpClient API 下载 zip 存档失败

Angular - Downloading a zip archive using HttpClient API fails

在我们的 Angular5 网络应用程序中,我们调用 API 来获取 zip 存档(后端是使用 SharpZipLib 的 ASP.NET Core 2.1)。它使用 Angular 的旧 HTTP API 工作正常:)

但是由于我们升级到新的 HttpClient API(使用 HttpInterceptor 处理 XSRF),现在下载失败且没有任何解释(API 的响应是 200 OK)

这是实际代码:

  public getCsvArchive(url: string) {
    const headers = new HttpHeaders({ 'responseType': 'arraybuffer' });
    return this._http.get(url, { headers } )
      .timeout(ServiceConfigurator.TIMEOUT)
      .catch(this.handleError);
  }

出于某些原因,如果我直接将 "responseType: arraybuffer" 放入 get 方法中,下载工作正常....但检索到的文件的大小不是我们预期的(存档甚至无法打开)

也许拦截器是罪魁祸首?

@Injectable()
export class RequestInterceptor implements HttpInterceptor {
    private getTokenName = 'XSRF-TOKEN';
    private setTokenName = 'X-XSRF-TOKEN';
    private tokenValue: string;
    constructor(private _cookieService: CookieService) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let headers = new HttpHeaders({
            'Content-Type': 'application/json',            
            'Access-Control-Allow-Origin': '*',
            'Cache-Control': 'no-cache',
            'if-none-match': 'no-match-for-this',
            'Pragma': 'no-cache'
        });

        if (req.method !== 'GET') {
            if (this.tokenValue) {
                headers = headers.append(this.setTokenName, this.tokenValue);
            }
            return next.handle(req.clone({ headers }));
        } else {
            return next.handle(req.clone({ headers })).do((ev: HttpEvent<any>) => {
                if (ev instanceof HttpResponse) {
                    if (environment.use_dp) {
                        console.log(this._cookieService.get(this.getTokenName));
                        this.tokenValue = this._cookieService.get(this.getTokenName);
                    }
                    this._cookieService.put(this.getTokenName, this.tokenValue);
                }
            });
        }
    }
}

尝试这样的事情:

使用 blob:

服务调用:

this.type = 'application/zip'

getFile(url:string,type:string){
        let headers = new HttpHeaders().append("Authorization", "Bearer " + token)
        return this.httpClient.get(url, {responseType: 'arraybuffer',headers:headers});
    }

分量:

从服务器获取文件:

getFile() {
        this.fileService.getFile('url, this.type).subscribe(respData => {
            this.downLoadFile(respData, this.type);
        }, error => {
           console.log(error);
        });
    }

下载文件:

     * Method is use to download file.
     * @param data - Array Buffer data
     * @param type - type of the document.
     */
    downLoadFile(data: any, type: string) {
        var blob = new Blob([data], { type: type.toString() });
        var url = window.URL.createObjectURL(blob);
        var pwa = window.open(url);
        if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
            alert('Please disable your Pop-up blocker and try again.');
        }
    }

好吧,我发现了问题所在,但我忘了包含另一段代码,所以我将以 UnluckyAj 响应为例,因为它非常相似;)

这是我在迁移到新的 HttpClient 之前所拥有的 API

getFile() {
        this.fileService.getFile('url', this.type).subscribe(respData => {
            this.downloadFile(respData._body, this.type);
        }, error => {
           console.log(error);
        });
    }

此时 'respData' 是一个特殊的对象,它有一个名为“_body”的 属性,其中包含我感兴趣的全部内容:)

但是在移动到 HttpClient 之后,'respData' 已经是一个 'Blob' 并且没有像以前那样的 '_body' 属性。因此,通过将代码更改为与 UnluckyAj (+1) 相同的代码:

getFile() {
        this.fileService.getFile('url', this.type).subscribe(respData => {
            this.downloadFile(respData., this.type);
        }, error => {
           console.log(error);
        });
    }

它现在可以工作了 :) 但是在 downloadFile 方法中我使用了 FileSaver 库,因为我们的 webapp 不是 Progressive WebApp ;)

  downloadFile(data: any) {
    const blob = new Blob([data], { type: 'application/zip' });
    const fileName = 'CSV_CONTENT.ZIP';
    FileSaver.saveAs(blob, fileName);
  }