如何在运行时以Springboot生成的角度下载PDF文件?

时间:2020-03-25 21:26:42

标签: angular spring-boot

我试图在Springboot Service中下载运行时生成的PDF文件(使用iTextPDF生成的PDF),并希望通过angular 6.0在新选项卡中打开该文件。 我尝试遵循此How to download a pdf file in angular which is generated on my server(springboot)?,但收到错误消息“无法加载PDF文档”。 代码有什么问题?

角度组件:

this.service.PrintPDF(this.quotations).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);
    }
  );

Angular服务:

PrintPDF(quotations: Quotation[]) {

        let url = this.PDF_URL;
        var authorization = 'Bearer ' + sessionStorage.getItem("key");

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

        return this.http.post<Blob>(url, quotations, {
            headers: headers, responseType:'blob' as 'json'}).pipe(map(
            (response) => {
                return response;
            },
            (error) => {console.log(error.json());}
        ));

Springboot控制器:

@PostMapping(value = "/generatepdf")
    public void downloadFile(@RequestBody List<QuotationDTO> quotationDTOs, HttpServletRequest request, HttpServletResponse response) {

        try {
            quotationService.GeneratePDF(quotationDTOs, request, response);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

Springboot服务:

public String  GeneratePDF(java.util.List<QuotationDTO> quotationDTOs, HttpServletRequest request,
                           HttpServletResponse response) throws DocumentException, IOException {

        response.setContentType("application/blob");

        // Response header
        response.setHeader("Pragma", "public");
        response.setHeader("responseType", "blob");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + "Quotation" + "\"");
//        OutputStream os = response.getOutputStream();

        Document document = new Document(PageSize.A4, 50, 50, 5 , 5);
        String current = sdf.format(new Timestamp(System.currentTimeMillis())).toString();
        String reportName = "report"+current;

        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(<Path>));
        document.open();
        // Write Content
        document.close();
        PdfWriter.getInstance(document, response.getOutputStream());

        return reportName+".pdf";
    }

1 个答案:

答案 0 :(得分:0)

我找到了解决问题的方法。我试图从内存中发送PDF。现在在一个位置上创建pdf,并从该位置发送阅读。 不确定iTextPDF是否支持内存pdf创建。

Springboot服务:

public Resource GeneratePDF(java.util.List<QuotationDTO> quotationDTOs, HttpServletRequest request)
        throws DocumentException, IOException {
    Document document = new Document(PageSize.A4, 50, 50, 5 , 5);
    String current = sdf.format(new Timestamp(System.currentTimeMillis())).toString();
    String reportName = "report"+current;
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("PATH"));
    document.open();
    //Write PDF
    document.close();
    try {
        Path filePath = this.fileStorageLocation.resolve(reportName+".pdf").normalize();
        Resource resource = new UrlResource(filePath.toUri());
        if (resource.exists()) {
            return resource;
        } else {
            throw new MyFileNotFoundException("File not found " + reportName+".pdf");
        }
    } catch (MalformedURLException ex) {
        throw new MyFileNotFoundException("File not found " + reportName+".pdf", ex);
    }
}

Springboot控制器:

@PostMapping(value = "/generatepdf")
public ResponseEntity<Resource> downloadFile(@RequestBody List<QuotationDTO> quotationDTOs, HttpServletRequest request) {

    try {
        Resource resource = quotationService.GeneratePDF(quotationDTOs, request);
        String contentType = null;
        try {
            contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
        } catch (IOException ex) {
        }
        // Fallback to the default content type if type could not be determined
        if(contentType == null) {
            contentType = "application/octet-stream";
        }
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                .body(resource);

    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Angular服务:

PrintPDF(quotations: Quotation[]) {
    let url = this.PDF_URL;
    var authorization = 'Bearer ' + sessionStorage.getItem("key");
    let headerOptions = new HttpHeaders({
        'Content-Type': 'application/json',
        'Accept': 'application/pdf',
        "Authorization": authorization
        //   'Accept': 'application/octet-stream', // for excel file
    });
    let requestOptions = { headers: headerOptions, responseType: 'blob' as 'blob' };
    this.http.post(url, quotations, requestOptions).pipe(map((data: any) => {
        let blob = new Blob([data], {
            type: 'application/pdf' // must match the Accept type
            // type: 'application/octet-stream' // for excel 
        });
        var link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        // link.download = 'samplePDFFile.pdf';
        link.target = '_blank';
        link.click();
        window.URL.revokeObjectURL(link.href);

    })).subscribe((result: any) => {
    });
}

Angular Component只是在调用Angular Service