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

Posted

技术标签:

【中文标题】如何下载我的服务器(springboot)上生成的角度pdf文件?【英文标题】:How to download a pdf file in angular which is generated on my server(springboot)? 【发布时间】:2019-12-21 04:05:58 【问题描述】:

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

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

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

我访问了 *** 上的以下问题,以找到一些解决方案: 1.PDF Blob is not showing content, Angular 2 2.How can I get access to the Angular 2 http response body without converting it to string or json? 3.converting byte stream in HTTPResponse body into a pdf file 4.Send File with SpringBoot to 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);
        
      );
    

服务: getPDF(invoiceId : number) 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()); ));

在 Spring 启动中:

控制器:

@RestController @RequestMapping("/invoices") 公共类发票控制器 @自动连线 发票服务 invoiceService; @GetMapping(path = "/generatepdf/invoiceId") public void generateInvoicePdf(@PathVariable Integer invoiceId, HttpServletRequest 请求,HttpServletResponse 响应) invoiceService.generateInvoicePdf(invoiceId, request, response);

服务实现:

@覆盖 public String generateInvoicePdf(Integer invoiceId, HttpServletRequest request, HttpServletResponse response) //createPDF() 将创建一个 .pdf 文件 createPDF(pdfFilename, dto, dtoForSupplier); 如果(pdf文件名!= null) 尝试 文件文件=新文件(pdf文件名); FileInputStream is = new FileInputStream(file); response.setContentType("应用程序/blob"); // 响应头 response.setHeader("Pragma", "public"); response.setHeader("responseType", "blob"); response.setHeader("Content-Disposition", "attachment; filename=\"" + pdfFilename + "\""); // 从文件中读取并写入响应 输出流 os = response.getOutputStream(); System.out.println(os); 字节[] 缓冲区 = 新字节[(int) file.length()]; 国际化; 而 ((len = is.read(buffer)) != -1) os.write(buffer, 0, len); System.out.println(os); os.flush(); os.close(); is.close(); 捕捉(IOException e) e.printStackTrace(); 返回pdf文件名;

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

core.js:15724 ERROR 错误:请求正文既不是 blob 也不是数组缓冲区 在 Response.push../node_modules/@angular/http/fesm5/http.js.Body.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)>

【问题讨论】:

您能更具体地说明您遇到的问题吗?我不能轻易说出问题所在(这里有太多代码来找出问题所在)。 ServiceImplementation 中更改response.setContentType("application/pdf") 或告诉您在角度得到什么响应? @kgdesouz 我只想下载一个从基于spring的restful web服务发送到我的angular 6应用程序的pdf文件,你能给我一个如何实现的小例子吗? 转到angular.io/api/common/http/HttpClient#get。单击“15 个重载...”。找到返回 Observable 的那个。提示:这是第二个。查看您必须作为选项传递的内容以使用该重载(提示:它不是您需要传递的标头)。然后注意它返回一个 Observable。所以 observable 发出的 一个 Blob。不是具有 blob() 方法属性的对象,该属性将返回 Blob。 @AlirezaKhajavi 将代码更改为 response.setContentType("application/pdf") 但我仍然收到相同的错误消息 Error: The request body is not a blob or an array buffer 【参考方案1】:

正如@JBNizet 所建议的,我已经实现了 observable,如下所示:

组件:

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

服务:

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

我提到的网址:

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

【讨论】:

以上直接下载,在新标签页打开PDF不起作用 这对我有用(下载和打开一个新窗口)。但是,如果您使用打字稿,则需要将 document.createElement 的结果转换为

以上是关于如何下载我的服务器(springboot)上生成的角度pdf文件?的主要内容,如果未能解决你的问题,请参考以下文章

Beanstalk:如何将服务器上生成的文件同步回 beanstalk 存储库?

如何在 xls 中下载由 play 1.2.7 后端在 java 上生成的 html 表的内容

我可以对 iOS 上生成的 pdf 文件中的图像使用 JPEG 压缩吗?

Puttygen 和 NodeJS 上生成的 RSA 密钥的长度不同

在 iOS10 上生成的 GIF 图像不再在浏览器上永远循环

关于从kafka采集数据到flume,然后落盘到hdfs上生成的一堆小文件的总结