背景
我使用
pdf-lib
在网络应用程序的后端动态生成 PDF 文件。然后,我以 Uint8Array
的形式将 PDF 字节发送到前端,以便打开一个新选项卡,该选项卡将在应用程序前端之外显示该文件。
问题
虽然使用所需的
Uint8Array
有效负载成功完成了请求,但新选项卡 (Chrome) 中出现错误警报,显示:
错误
无法加载 PDF 文档。
Uint8Array
数据位于响应正文中:
{
success: true,
data: {0: 37, 1: 80, 2: 68, 3: 70, 4: 45, ...}
}
我尝试过的
在将字节返回到前端之前,我可以使用
fs.readFileSync()
方法在我的 PC 上保存和访问 PDF 文件。
我尝试同时使用 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')
}
看来问题是我不能直接在 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');
}