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

时间:2019-08-14 15:05:57

标签: angular rest spring-boot

“我想将从基于Spring的静态Web服务发送的.pdf文件下载到我的angular应用程序。如何下载它,我在我的angular应用程序或spring boot上缺少某些代码吗?”

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

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

我在StackOverflow上访问了以下问题,以找到一些解决方案: 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);
        }
      );
    }

服务:

    public class Chat extends AppCompatActivity {
    private DatabaseReference Database;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);
        final UserLocalStore localStore = new UserLocalStore(Chat.this);
        Database = FirebaseDatabase.getInstance().getReference("Messages");
        final TextView Chat_Window=(TextView)findViewById(R.id.chat_window);
        Database.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @androidx.annotation.Nullable String s) {
                Log.e("DatasnapShot",dataSnapshot.getKey().toString());

                Chat_Window.setText(dataSnapshot.getValue().toString());
            }
            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @androidx.annotation.Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @androidx.annotation.Nullable String s) {

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        Button SendMessage = (Button)findViewById(R.id.send);
        SendMessage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String messageText = Chat_Window.getText().toString();            
         Database.push().setValue((localStore.getUserData().get(0).toString()));
                Database.push().setValue(ChatType.getText().toString());
                Chat_Window.append(ChatType.getText().toString());
                ChatType.setText("");
            }
        });
            Button Signout = (Button)findViewById(R.id.signout);
    {
        Signout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            UserLocalStore localStore=new UserLocalStore(Chat.this);
            localStore.LogOut();
            FirebaseAuth.getInstance().signOut();
            Intent intent = new Intent(Chat.this,MainActivity.class);
                startActivity(intent);
            }
        });
    } 
    }
}

在春季启动中:

控制器:


    getPDF(invoiceId : number)
         {
             this.url = this.main_url + '/invoices/generatepdf/'+invoiceId;
             const headers = new Headers({ 'Content-Type': 'application/json', 
             "Authorization": authorization, responseType : 'blob'});
             return this.http.get(this.url, { headers : headers})
                 .pipe(map(
                     (response) => {
                         return response;
                     },
                     (error) => {
                         console.log(error.json());
                     }
                 ));
         }

ServiceImplementation:


    @RestController
    @RequestMapping("/invoices")
    public class InvoiceController {

    @Autowired
        InvoiceService invoiceService;

    @GetMapping(path = "/generatepdf/{invoiceId}")
        public void generateInvoicePdf(@PathVariable Integer invoiceId,
                HttpServletRequest request,HttpServletResponse response) {
            invoiceService.generateInvoicePdf(invoiceId, request, response);
    }

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

  

core.js:15724错误错误:请求正文不是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)>

1 个答案:

答案 0 :(得分:0)

按照@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);
        }
      );
    }

服务:

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'});
     }
我引用的

URL:

  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