如何下载在我的服务器(springboot)上生成的角度pdf文件?

Abh*_*dam 5 rest spring-boot angular

“我想下载一个从基于 Spring 的 Restful Web 服务发送到我的 Angular 应用程序的 .pdf 文件。如何下载它,我的 Angular 应用程序或 Spring Boot 上是否缺少一些代码?”

我从 Angular 6 应用程序向我的 spring-boot 服务器发送 HTTP GET 请求,该服务器生成一个 .pdf 文件,然后将此 .pdf 文件作为 blob 发送给我,但是当我尝试在我的 Angular 一侧创建一个 blob 时,打开pdf,显示以下错误:

。ERROR 错误:请求正文不是 blob 或数组缓冲区

我在 StackOverflow 上访问了以下问题,以找到一些解决方案: 1. PDF Blob 未显示内容,Angular 2 2.如何访问 Angular 2 http 响应正文而不将其转换为字符串或 json? 3.将 HTTPResponse 主体中的字节流转换为 pdf 文件 4.使用 SpringBoot 将文件发送到 Angular2

在 Angular 应用程序中: 组件:

 

getPDF(){
      this.apiService.getPDF(this.invoiceId)
      .subscribe(
        (data) => {
          //data.blob() doesnt work properly
          var file = new Blob([data.blob()], { type: 'application/pdf' })
          var fileURL = URL.createObjectURL(file);
          window.open(fileURL); // if you want to open it in new tab
          var a         = document.createElement('a');
          a.href        = fileURL; 
          a.target      = '_blank';
          a.download    = 'bill.pdf';
          document.body.appendChild(a);
          a.click();
        },
        (error) => {
          console.log('getPDF error: ',error);
        }
      );
    }
Run Code Online (Sandbox Code Playgroud)

服务:

    getPDF(发票ID:号码)
         {
             this.url = this.main_url + '/invoices/generatepdf/'+invoiceId;
             const headers = new headers({ 'Content-Type': 'application/json',
             “授权”:授权,响应类型:'blob'});
             返回 this.http.get(this.url, { headers : headers})
                 .管道(地图(
                     (回应)=> {
                         返回响应;
                     },
                     (错误)=> {
                         console.log(error.json());
                     }
                 ));
         }

在春季启动中:

控制器:

    @RestController
    @RequestMapping("/发票")
    公共类发票控制器{

    @Autowired
        InvoiceService发票服务;

    @GetMapping(路径 = "/generatepdf/{invoiceId}")
        公共无效generateInvoicePdf(@PathVariable整数发票Id,
                HttpServletRequest 请求,HttpServletResponse 响应){
            InvoiceService.generateInvoicePdf(invoiceId, 请求, 响应);
    }

服务实施:

    @覆盖
        公共字符串generateInvoicePdf(整数发票Id,HttpServletRequest请求,HttpServletResponse响应){

             //createPDF() 将创建一个 .pdf 文件
            createPDF(pdfFilename, dto, dtoForSupplier);
            if (pdf文件名!= null) {
                尝试 {
                    文件 文件 = 新文件(pdf文件名);
                    FileInputStream = new FileInputStream(文件);
                    response.setContentType(“应用程序/blob”);

                    // 响应头
                    response.setHeader("Pragma", "public");
                    response.setHeader("responseType", "blob");
                    response.setHeader("Content-Disposition", "附件; filename=\"" + pdfFilename + "\"");

                    // 从文件中读取并写入响应
                    OutputStream os = response.getOutputStream();
                    System.out.println(os);
                    byte[] buffer = new byte[(int) file.length()];

                    int 长度;
                    while ((len = is.read(buffer)) != -1) {
                        os.write(缓冲区, 0, 长度);
                    }

                    System.out.println(os);
                    os.flush();
                    os.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            返回pdf文件名;
        }

我希望在浏览器中下载 .pdf 文件并打开它并查看其内容,但我收到错误:

core.js:15724 ERROR 错误:请求正文不是 Response.push../node_modules/@angular/http/fesm5/http.js.Body.blob 处的 blob 或数组缓冲区 (http.js:782 )在 SafeSubscriber._next (invoice-details.component.ts:212) 在 SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196) 在 SafeSubscriber.push。 ./node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:134) 在 Subscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next (Subscriber.js :77) 在 Subscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54) 在 MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map .js.MapSubscriber._next (map.js:41) 在 MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54) 在 XMLHttpRequest.onLoad (http.js :1070)在ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask(zone.js:423)>

Abh*_*dam 9

根据@JBNizet的建议,我已经实现了可观察的,如下所示:

成分:

getPDF(){
      this.apiService.getPDF(this.invoiceId)
      .subscribe(
        (data: Blob) => {
          var file = new Blob([data], { type: 'application/pdf' })
          var fileURL = URL.createObjectURL(file);

// if you want to open PDF in new tab
          window.open(fileURL); 
          var a         = document.createElement('a');
          a.href        = fileURL; 
          a.target      = '_blank';
          a.download    = 'bill.pdf';
          document.body.appendChild(a);
          a.click();
        },
        (error) => {
          console.log('getPDF error: ',error);
        }
      );
    }
Run Code Online (Sandbox Code Playgroud)

服务:

getPDF(invoiceId : number): Observable<Blob>
     {
         this.url = this.main_url + '/invoices/generatepdf/'+invoiceId;
         var authorization = 'Bearer '+sessionStorage.getItem("access_token");

         const headers = new HttpHeaders({ 'Content-Type': 'application/json',
         "Authorization": authorization, responseType : 'blob'});

         return this.httpClient.get<Blob>(this.url, { headers : headers,responseType : 
         'blob' as 'json'});
     }
Run Code Online (Sandbox Code Playgroud)

我提到的网址:

  1. 重载#2: https: //angular.io/api/common/http/HttpClient#get
  2. 使用 Http Post 预览 Blob: https://dzone.com/articles/how-to-preview-blobs-with-http-post-and-angular-5