You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:50:23