0

I'm using handlebars & puppeteer to generate a PDF report on my express api/server side. Using insomnia to trigger the API, it returns a complete PDF, exactly as I expect. When I have client side React app download it, it saves the correct number of pages, but empty. I've tried a number of ways of downloading the file, headers on API side. Here's the current code.

front end:

const res = await getDashboard(company, category, country, endDate, startDate);
const blob = new Blob([res], { type: 'application/pdf' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'amazon.pdf';
a.click();

Server side:

const pdf = await genReport(data);
res.contentType('application/pdf');
res.header('Pragma', 'public');
res.header('Cache-Control', 'max-age=0');
res.setHeader('Content-disposition', 'attachment;filename=AmazonReport.pdf');
res.type('application/pdf');
res.send(pdf);

I'm not sure where I've gone wrong. Since insomnia receives the PDF fine, I assume its client side handling. Please help.

Andymanic
  • 11
  • 2
  • Sending files is always a pain. Have you tried base64 encoding it on the back end first and then decoding it to binary on the front end? https://stackoverflow.com/questions/51981473/downloaded-pdf-looks-empty-although-it-contains-some-data – georgedum Jun 06 '20 at 22:22
  • 1
    @georgedum I had to faff around with working out how to convert to base64 in typescript, but that's solved it! Thank you for the help! – Andymanic Jun 06 '20 at 22:45

1 Answers1

1

@georgedum has pointed me in the right direction here, problem is now solved. Here's the updated/fixed code: Client side:

const res = await getDashboard(company, category, country, endDate, startDate);
const binaryString = window.atob(res);
const binaryLen = binaryString.length;
const bytes = new Uint8Array(binaryLen);
for (let i = 0; i < binaryLen; i++)
{
    const ascii = binaryString.charCodeAt(i);
    bytes[i] = ascii;
}
const blob = new Blob([bytes], { type: 'application/pdf' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'amazon.pdf';
a.click();

Server side:

const pdf = await genReport(data);
const encodedPdf = Buffer.from(pdf).toString('base64');
res.contentType('application/pdf');
res.header('Pragma', 'public');
res.header('Cache-Control', 'max-age=0');
res.setHeader('Content-disposition', 'attachment;filename=AmazonReport.pdf');
res.type('application/pdf');
res.send(encodedPdf);
Andymanic
  • 11
  • 2