代码之家  ›  专栏  ›  技术社区  ›  Mike Omeiri Kouider

下载的PDF虽然包含一些数据,但看起来是空的

  •  2
  • Mike Omeiri Kouider  · 技术社区  · 7 年前

    我试图用JavaScript实现PDF文件下载功能。
    作为对 POST oResult 数据容器,片段):

    %PDF-1.4%4 0目标<>streamx

    let blob = new Blob([oResult], {type: "application/pdf"});
    
    let link = document.createElement('a');
    
    link.href = window.URL.createObjectURL(blob);
    link.download = "tstPDF";
    
    link.click();
    

    结果,当我点击一个按钮时 ,它包含正确的页数,但PDF本身是空的,不显示任何内容,尽管它是6kb。

    当我测试生成PDF的Java服务器端模块时,一切正常,它发送 InputStream ServletOutputStream . 因此,我假设问题出在客户端的某个地方,可能是 MIME , BLOB encoding ,或类似。

    你知道为什么生成的PDF不显示任何数据吗?

    2 回复  |  直到 6 年前
        1
  •  9
  •   Mike Omeiri Kouider    7 年前

    我解决了这个问题。 确保服务器将数据发送到 Base64

    服务器端:

    OutputStream pdfStream = PDFGenerator.pdfGenerate(data);
    
    String pdfFileName = "test_pdf";
    
    // represent PDF as byteArray for further serialization
    byte[] byteArray = ((java.io.ByteArrayOutputStream) pdfStream).toByteArray();
    
    // serialize PDF to Base64
    byte[] encodedBytes = java.util.Base64.getEncoder().encode(byteArray);
    
    response.reset();
    response.addHeader("Pragma", "public");
    response.addHeader("Cache-Control", "max-age=0");
    response.setHeader("Content-disposition", "attachment;filename=" + pdfFileName);
    response.setContentType("application/pdf");
    
    // avoid "byte shaving" by specifying precise length of transferred data
    response.setContentLength(encodedBytes.length);
    
    // send to output stream
    ServletOutputStream servletOutputStream = response.getOutputStream();
    
    servletOutputStream.write(encodedBytes);
    servletOutputStream.flush();
    servletOutputStream.close();
    

    客户端:

    let binaryString = window.atob(data);
    
    let binaryLen = binaryString.length;
    
    let bytes = new Uint8Array(binaryLen);
    
    for (let i = 0; i < binaryLen; i++) {
        let ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    
    let blob = new Blob([bytes], {type: "application/pdf"});
    
    let link = document.createElement('a');
    
    link.href = window.URL.createObjectURL(blob);
    link.download = pdfFileName;
    
    link.click();
    

        2
  •  1
  •   jeloVilla    6 年前

    多亏了这个。真的很管用。

    顺便说一下,下面是我如何使用spring控制器和ajax以及jasper生成的pdf

    控制器:

    public ResponseEntity<?> printPreview(@ModelAttribute("claim") Claim claim)
    {
        try
        {
            //Code to get the byte[] from jasper report.
            ReportSource source = new ReportSource(claim);
            byte[] report = reportingService.exportToByteArrayOutputStream(source);
    
            //Conversion of bytes to Base64
            byte[] encodedBytes = java.util.Base64.getEncoder().encode(report);
    
            //Setting Headers
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/pdf"));
            headers.setContentDispositionFormData("pdfFileName.pdf", "pdfFileName.pdf");
            headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
            headers.setContentLength(encodedBytes.length);
    
            return new ResponseEntity<>(encodedBytes, headers, HttpStatus.OK);
        }
        catch (Exception e)
        {
            LOG.error("Error on generating report", e);
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
     }
    

        $.ajax({
           type: "POST",
           url: "",
           data: form.serialize(), //Data from my form
           success: function(response)
           {
                    let binaryString = window.atob(response);
                    let binaryLen = binaryString.length;
                    let bytes = new Uint8Array(binaryLen);
    
                    for (let i = 0; i < binaryLen; i++) {
                        let ascii = binaryString.charCodeAt(i);
                        bytes[i] = ascii;
                    }
    
                    let blob = new Blob([bytes], {type: "application/pdf"});
                    let link = URL.createObjectURL(blob);
                    window.open(link, '_blank');
           },
           error: function()
           {
    
           }
         });
    

    这将在新窗口中加载pdf。

    参考文献: Return generated pdf using spring MVC