2

I used Puppeteer to generate a buffer with pdf information and send it to frontend. Here is the backend api:

exports.getPDF = async (req, res) => {
    const { content } = req.query;
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.setContent(`
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>HTML to PDF Example</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
      </head>
      <body>
        ${content}
      </body>
      </html>
      `);
    const buffer = await page.pdf();
    await browser.close();
    
    return res.apiResponse(buffer);
};

Then I tried to convert the buffer to pdf file and open it but failed, It said failed to load PDF document.

What I've done on front end:

await dispatch({
    type: 'resume/fetchResumePDF',
    payload: {
        content: resumeContent
    }
});
console.log(this.props.resumePDF);

const file = new Blob(this.props.resumePDF.data, {
    type: 'application/pdf'
});
const getFile = file && window.URL.createObjectURL(file);
window.open(getFile, "_blank");

The console.log buffer is as below:

enter image description here

Aziza Kasenova
  • 1,501
  • 2
  • 10
  • 22
FOREST
  • 328
  • 1
  • 3
  • 11

3 Answers3

5

This worked for me when creating a new Blob. I was able to use Shankar's code this way.

new Blob([new Uint8Array(this.props.resumePDF.data).buffer]);

// e.g. pass the array - new Blob([new Uint8Array([1,2,3,4]).buffer]);
const url = window.URL.createObjectURL(new Blob([new Uint8Array(this.props.resumePDF.data).buffer]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'yourcoolpdf.pdf');
document.body.appendChild(link);
link.click();
Nilebac
  • 191
  • 1
  • 10
  • Your solution worked for me as well. Thank you soo much :) – Shikhar Shukla Dec 11 '21 at 15:04
  • This is partially working for me, the PDF is opening, but all the pages are empty, any idea how do I find what's wrong? – Prajwal Kulkarni Jan 24 '22 at 18:34
  • @PrajwalKulkarni try setting the headers to accept pdf type : responseType: 'arraybuffer', headers: { Accept: 'application/pdf', } – Nilebac Jan 25 '22 at 19:38
  • @Nilebac If the responseType is `arraybuffer`, won't that be the only data fetched? I'm wanting to query other data at the same too(a JSON object to be precise) that includes the array buffer, any idea on how do I go about this? – Prajwal Kulkarni Jan 26 '22 at 17:53
0

On the frontend, you can create ObjectURL that can be downloaded using

const url = window.URL.createObjectURL(new Blob([this.props.resumePDF]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'yourcoolpdf.pdf');
document.body.appendChild(link);
link.click();
Shankar Regmi
  • 854
  • 1
  • 7
  • 16
0

As mentioned here, if you're using Axios.get() on the front-end, make sure to add the { responseType: 'blob' } option:

const res = await axios.get("/api/pdf-route", 
    { responseType: 'blob' } // <----- ***
);


More info:

My back-end returns a Buffer (using "@react-pdf/renderer" package and it's renderToBuffer function)

const pdf = /* <the return value of renderToBuffer> */;
res.setHeader('Content-Type', 'application/pdf');
return res.send(pdf);

And my front-end:

const { data } = await axios.get("/api/student/pdf", 
    { responseType: 'blob' }
);

downloadPdf(data, "myFileName.pdf");

function downloadPdf(pdfBlob: Blob, filename: string) {
    const pdfBlob = new Blob([pdfBlob], { type: 'application/pdf' });
    const downloadUrl = URL.createObjectURL(pdfBlob);
    const link = document.createElement("a");
    link.href = downloadUrl;
    link.download = filename;
    link.click();
    URL.revokeObjectURL(downloadUrl);
}

Shani Kehati
  • 427
  • 5
  • 10