typescript Angular 6 从rest api下载文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52154874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:58:03  来源:igfitidea点击:

Angular 6 Downloading file from rest api

resttypescriptangular6

提问by gmexo

I have my REST API where I put my pdf file, now I want my angular app to download it on click via my web browser but I got HttpErrorResponse

我有我的 REST API,我把我的 pdf 文件放在那里,现在我希望我的 angular 应用程序通过我的网络浏览器点击下载它,但我得到了 HttpErrorResponse

"Unexpected token % in JSON at position 0"

“JSON 中位置 0 的意外标记 %”

"SyntaxError: Unexpected token % in JSON at position 0? at JSON.parse (

“SyntaxError: Unexpected token % in JSON at position 0? at JSON.parse (

this is my endpoint

这是我的终点

    @GetMapping("/help/pdf2")
public ResponseEntity<InputStreamResource> getPdf2(){

    Resource resource = new ClassPathResource("/pdf-sample.pdf");
    long r = 0;
    InputStream is=null;

    try {
        is = resource.getInputStream();
        r = resource.contentLength();
    } catch (IOException e) {
        e.printStackTrace();
    }

        return ResponseEntity.ok().contentLength(r)
                .contentType(MediaType.parseMediaType("application/pdf"))
                .body(new InputStreamResource(is));

}

this is my service

这是我的服务

  getPdf() {

this.authKey = localStorage.getItem('jwt_token');

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type':  'application/pdf',
    'Authorization' : this.authKey,
    responseType : 'blob',
    Accept : 'application/pdf',
    observe : 'response'
  })
};
return this.http
  .get("http://localhost:9989/api/download/help/pdf2", httpOptions);

}

}

and invocation

和调用

this.downloadService.getPdf()
  .subscribe((resultBlob: Blob) => {
  var downloadURL = URL.createObjectURL(resultBlob);
  window.open(downloadURL);});

采纳答案by gmexo

I resolved it as follows:

我是这样解决的:

// header.component.ts
this.downloadService.getPdf().subscribe((data) => {

  this.blob = new Blob([data], {type: 'application/pdf'});

  var downloadURL = window.URL.createObjectURL(data);
  var link = document.createElement('a');
  link.href = downloadURL;
  link.download = "help.pdf";
  link.click();

});



//download.service.ts
getPdf() {

  this.authKey = localStorage.getItem('jwt_token');

  const httpOptions = {
    responseType: 'blob' as 'json',
    headers: new HttpHeaders({
      'Authorization': this.authKey,
    })
  };

  return this.http.get(`${this.BASE_URL}/help/pdf`, httpOptions);
}

回答by Yennefer

I solved the issue in this way (please note that I have merged multiple solutions found on stack overflow, but I cannot find the references. Feel free to add them in the comments).

我用这种方式解决了这个问题(请注意,我已经合并了在堆栈溢出时找到的多个解决方案,但我找不到引用。请随意在评论中添加它们)。

In My service I have:

在我的服务中,我有:

public getPDF(): Observable<Blob> {   
//const options = { responseType: 'blob' }; there is no use of this
    let uri = '/my/uri';
    // this.http refers to HttpClient. Note here that you cannot use the generic get<Blob> as it does not compile: instead you "choose" the appropriate API in this way.
    return this.http.get(uri, { responseType: 'blob' });
}

In the component, I have (this is the part merged from multiple answers):

在组件中,我有(这是从多个答案合并的部分):

public showPDF(): void {
    this.myService.getPDF()
        .subscribe(x => {
            // It is necessary to create a new blob object with mime-type explicitly set
            // otherwise only Chrome works like it should
            var newBlob = new Blob([x], { type: "application/pdf" });

            // IE doesn't allow using a blob object directly as link href
            // instead it is necessary to use msSaveOrOpenBlob
            if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                window.navigator.msSaveOrOpenBlob(newBlob);
                return;
            }

            // For other browsers: 
            // Create a link pointing to the ObjectURL containing the blob.
            const data = window.URL.createObjectURL(newBlob);

            var link = document.createElement('a');
            link.href = data;
            link.download = "Je kar.pdf";
            // this is necessary as link.click() does not work on the latest firefox
            link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));

            setTimeout(function () {
                // For Firefox it is necessary to delay revoking the ObjectURL
                window.URL.revokeObjectURL(data);
                link.remove();
            }, 100);
        });
}

The code above works in IE, Edge, Chrome and Firefox. However, I don't really like it, as my component is pulluted with browser specific stuff which will surely change over time.

上面的代码适用于 IE、Edge、Chrome 和 Firefox。但是,我真的不喜欢它,因为我的组件是用浏览器特定的东西拉出来的,这些东西肯定会随着时间的推移而改变。

回答by David Kroese

This also works in IE and Chrome, almost the same answer only for other browsers the answer is a bit shorter.

这也适用于 IE 和 Chrome,几乎相同的答案仅适用于其他浏览器,但答案要短一些。

getPdf(url: string): void {
    this.invoiceService.getPdf(url).subscribe(response => {

      // It is necessary to create a new blob object with mime-type explicitly set
      // otherwise only Chrome works like it should
      const newBlob = new Blob([(response)], { type: 'application/pdf' });

      // IE doesn't allow using a blob object directly as link href
      // instead it is necessary to use msSaveOrOpenBlob
      if (window.navigator && window.navigator.msSaveOrOpenBlob) {
          window.navigator.msSaveOrOpenBlob(newBlob);
          return;
      }

      // For other browsers:
      // Create a link pointing to the ObjectURL containing the blob.
      const downloadURL = URL.createObjectURL(newBlob);
        window.open(downloadURL);
    });
  }