Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
587 views
in Technique[技术] by (71.8m points)

javascript - Downloaded PDF looks empty although it contains some data

I'm trying to implement a PDF file download functionality with JavaScript.
As a response to a POST request I get a PDF file, in Chrome DevTools console it looks like (the oResult data container, fragment):

"%PDF-1.4?%?????4 0 obj?<>stream?x??

Now I'm trying to initialize the download process:

let blob = new Blob([oResult], {type: "application/pdf"});

let link = document.createElement('a');

link.href = window.URL.createObjectURL(blob);
link.download = "tstPDF";

link.click();

As a result, upon a click on a button I get tstPDF.pdf, it contains the correct number of pages, but the PDF itself is empty, no content is displayed, although it is 6 KB.

When I test the Java server-side module, which generates the PDF, everything is working fine, it sends InputStream through ServletOutputStream. Thus I assume that the issue is somewhere on a client side, perhaps something with MIME, BLOB, encoding, or similar.

Do you have any idea why the generated PDF doesn't display any data?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I solved the issue. The problem was in a way the data is delivered from the server to the client. It is critical to assure that the server sends the data in Base64 encoding, otherwise the client side can't deserialize the PDF string back to the binary format. Below, you can find the full solution.

Server-side:

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

Client side:

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

Reference topics:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...