首页 > 解决方案 > Next.js Puppeteer PDF 可下载链接返回错误

问题描述

我在 Next.js 后端路由中使用 puppeteer 从给定的 URL 生成 PDF。之后,我返回该 pdf 以自动从我的客户端下载该 PDF。

目前我从我的 PDF 输出中得到这个错误:

VM640:1 Uncaught (in promise) SyntaxError: Unexpected token % in JSON at position 0

我的 PDF 输出与此类似:

%PDF-1.4
%����
1 0 obj
<</Creator (Chromium)

这是后端部分,我使用 puppeteer 生成我的 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

这是接收 PDF 数据并开始下载的前端部分:

调用api路由:

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)
}

这就是我尝试生成自动 PDF 下载的方式:

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

标签: javascriptnode.jspdfnext.jspuppeteer

解决方案


推荐阅读