I am using puppeteer in my Next.js backend routes to generate a PDF from a given URL. After that I return that pdf to automatically download that PDF from my client.
Currently I get this error from my PDF output:
VM640:1 Uncaught (in promise) SyntaxError: Unexpected token % in JSON at position 0
My PDF output looks similar to this:
%PDF-1.4
%����
1 0 obj
<</Creator (Chromium)
This is the backend part, in which I use puppeteer to generate my PDF:
import puppeteer from 'puppeteer'
async function printPdf(req, res) {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(`http://localhost:3000/real-estate-pdf/${req.body.slug}`, {
waitUntil: 'networkidle2',
})
const pdf = await page.pdf({
path: 'test.pdf',
printBackground: true,
format: 'a4',
})
await browser.close()
return pdf
}
async function generatePdf(req, res) {
const pdf = await printPdf(req, res)
res.send(pdf)
}
export default generatePdf
And this is the frontend part to receive the PDF data and to start a download:
Call the api route:
const create = async () => {
const pdfCall = await fetch('/api/pdf', {
body: JSON.stringify({
slug: fileName.split('.')[0],
}),
headers: { "Content-Type": "application/json" },
responseType: 'arraybuffer',
method: 'POST',
})
const { error } = await pdfCall.json()
console.log('error: ' + error)
}
This is how I try to generate the automatic PDF download:
function base64ToArrayBuffer(data) {
var binaryString = window.atob(data)
var binaryLen = binaryString.length
var bytes = new Uint8Array(binaryLen)
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i)
bytes[i] = ascii
}
return bytes
}
function clientPdfDownload(base64Data) {
var arrBuffer = base64ToArrayBuffer(base64Data)
// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
var newBlob = new Blob([arrBuffer], { type: 'application/pdf' })
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob)
return
}
// For other browsers:
// Create a link pointing to the ObjectURL containing the blob.
var data = window.URL.createObjectURL(newBlob)
var link = document.createElement('a')
document.body.appendChild(link) //required in FF, optional for Chrome
link.href = data
link.download = 'file.pdf'
link.click()
window.URL.revokeObjectURL(data)
link.remove()
}