在新的浏览器选项卡中显示 Uint8Array 的 pdf

问题描述 投票:0回答:1

背景

我使用

pdf-lib
在网络应用程序的后端动态生成 PDF 文件。然后,我以
Uint8Array
的形式将 PDF 字节发送到前端,以便打开一个新选项卡,该选项卡将在应用程序前端之外显示该文件。

问题

虽然使用所需的

Uint8Array
有效负载成功完成了请求,但新选项卡 (Chrome) 中出现错误警报,显示: 错误 无法加载 PDF 文档。

Uint8Array
数据位于响应正文中:

{
    success: true,
    data: {0: 37, 1: 80, 2: 68, 3: 70, 4: 45, ...}
}

我尝试过的

  1. 在将字节返回到前端之前,我可以使用

    fs.readFileSync()
    方法在我的 PC 上保存和访问 PDF 文件。

  2. 我尝试同时使用 Chrome 和 Edge,但问题仍然存在。

后端代码

try {
        const pdfBytes = await pdfDoc.save()    // .save() method returns Promise<Uint8Array>
        const filePath = './dddd.pdf'
        fs.writeFileSync(filePath, pdfBytes)    // This line creates a file to PC successfully
        return pdfBytes
    } catch (err) {
        console.log('erroe while saving');
        console.log(err);
    }

前端代码

if (result.success) {
       const pdfBlob = new Blob([result.data], { type: 'application/pdf' })
       const pdfURL = URL.createObjectURL(pdfBlob)
       console.log(pdfURL);   // -->  blob:http://localhost:3000/8f168e27-934e-4d80-a479-31975e22eaa1
            
       window.open(pdfURL, '_blank')
 }
reactjs pdf blob uint8array
1个回答
0
投票

看来问题是我不能直接在 Uint8Array 上使用

.json()
JSON.stringefy()
方法并将其发送到前端,因为它会损坏二进制数据。

解决方案

在后端,我首先必须将 Uint8Array 转换为 base64string,将 json 中的字符串发送到前端,将 base64string 转换回 Uint8Array,然后创建 blob,创建临时 URL 并在新窗口中打开它选项卡。

后端代码:

import { NextRequest, NextResponse } from "next/server";
import { generatePdf } from "@/lib/pdf/generate/generatePDF";

export async function POST(req: NextRequest, res: NextResponse , context: {}) {
    try {
        console.log(' request reached!!!');
        
        const body = await req.json()
        const pdfBytes = await generatePdf(body)
        const base64PDF = Buffer.from(pdfBytes as Uint8Array).toString('base64')
        return NextResponse.json({success: true, data: base64PDF}, { status: 200 })
    } catch (err) {
        console.log('Error occurred while ...');
        console.log(err);
        return NextResponse.json({success: false}, { status: 500 })
    }
}

前端代码

if (result.success) {
            const base64PDF = result.data;
            const pdfBytes = new Uint8Array(atob(base64PDF).split('').map(char => char.charCodeAt(0)));
            const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
            const pdfURL = URL.createObjectURL(pdfBlob);
            window.open(pdfURL, '_blank');
}
© www.soinside.com 2019 - 2024. All rights reserved.