如何向Offscreen Document发送Blob/Uint8Array并解决PDF损坏问题?
Chrome扩展PDF下载损坏问题解决方案
问题根源
Chrome扩展的runtime.sendMessage在传递二进制数据(如ArrayBuffer)时,会自动将其序列化为普通JavaScript数组,导致字节数据格式错乱,最终生成的Blob无法正确解析为PDF,出现文件损坏、体积偏小的问题。
修复步骤
1. 修正后台脚本(background.js)的消息传递逻辑
将生成的PDF字节数据转换为Uint8Array传递,并利用Transferable Objects转移数据所有权,避免序列化丢失:
import './pdf-lib.min.js'; chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { (async () => { if (message.pdfUrls && message.pdfUrls.length > 0) { const urls = ["https://www.africau.edu/images/default/sample.pdf"]; await mergeAllPDFs(urls, "Test"); } })(); return true; }); async function mergeAllPDFs(urls, filename) { const numDocs = urls.length; const pdfDoc = await PDFLib.PDFDocument.create(); for (let i = 0; i < numDocs; i++) { console.log(`Fetching ${urls[i]}`) const donorPdf = await fetch(urls[i]); const donorPdfBytes = await donorPdf.arrayBuffer(); const donorPdfDoc = await PDFLib.PDFDocument.load(donorPdfBytes); const copiedPages = await pdfDoc.copyPages(donorPdfDoc, donorPdfDoc.getPageIndices()); copiedPages.forEach((page) => pdfDoc.addPage(page)); } const pdfDocBytes = await pdfDoc.save(); // 检查Offscreen文档是否已存在,避免重复创建 const hasOffscreen = await chrome.offscreen.hasDocument(); if (!hasOffscreen) { await chrome.offscreen.createDocument({ url: 'offscreen.html', reasons: ['BLOBS'], justification: '处理PDF Blob生成下载链接', }); } // 转换为Uint8Array并使用Transferable传递 const pdfUint8 = new Uint8Array(pdfDocBytes); chrome.runtime.sendMessage({ data: pdfUint8 }, { transfer: [pdfDocBytes] }, (response) => { console.log(response); const url = response.url; console.log(url); chrome.downloads.download({ url: url, filename: filename + ".pdf" }); }); }
2. 修正Offscreen脚本(offscreen.js)的Blob生成逻辑
将收到的数组重新转换为Uint8Array后再创建Blob,确保字节数据格式正确:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { // 将序列化后的数组转回Uint8Array const pdfBytes = new Uint8Array(message.data); const blob = new Blob([pdfBytes], { type: "application/pdf" }); const url = URL.createObjectURL(blob); sendResponse({ url: url }); return true; });
额外注意事项
- 确保
offscreen.html的配置正确,需包含引用offscreen.js的脚本标签:
<!DOCTYPE html> <html> <body> <script src="offscreen.js"></script> </body> </html>
- 扩展权限需在
manifest.json中声明"offscreen"、"downloads"以及目标PDF域名的"host_permissions"。
内容的提问来源于stack exchange,提问作者ExceptionFinder
相关产品推荐
相关产品推荐

