如何使用屏幕外文档在自定义 Chrome 扩展中下载 PDF

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

由于我生成的 PDF 的大小,无法进行 Base64 转换,我必须使用离屏功能。

基于这个答案->https://stackoverflow.com/a/75539867/8016254

我尝试下载一个 PDF 文件,该文件将在我的自定义 chrome 扩展中重新读取。

背景.js

import './pdf-lib.min.js';

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    (async () => {
        if (message.pdfUrls && message.pdfUrls.length > 0) {
            // Debug PDF
            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();
    const waiting = await chrome.offscreen.createDocument({
        url: 'offscreen.html',
        reasons: ['BLOBS'],
        justification: 'reason for needing the document',
    });
    chrome.runtime.sendMessage({
        data: pdfDocBytes
    }, (response) => {
        console.log(response);
        const url = response.url;
        console.log(url);
        chrome.downloads.download({
            url: url,
            filename: filename + ".pdf"
        });
    });

}

离屏.js

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    const blob = new Blob([message.data], { type: "application/pdf" });
    const url = URL.createObjectURL(blob);
    sendResponse({ url: url });
    return true;
});

生成的 PDF 似乎已损坏并且比预期小得多。有什么想法吗?

google-chrome-extension blob chrome-extension-manifest-v3 pdflib
1个回答
0
投票

问题:chrome.runtime.sendMessage 无法在 Chrome 中发送二进制数据。

解决方案:通过 navigator.serviceWorker 使用标准 Web 消息传递。

//背景

await chrome.offscreen.createDocument({url: 'offscreen.html', /*....*/});
const clientUrl = chrome.runtime.getURL('offscreen.html');
const client = (await clients.matchAll()).find(c => c.url === clientUrl);
const mc = new MessageChannel();
client.postMessage(blob, [mc.port2]);
const {data: blobUrl} = await new Promise(cb => (mc.port1.onmessage = cb));
chrome.downloads.download({
  url: blobUrl,
  filename: filename + '.pdf',
});

//offscreen.js

self.onmessage = e => {
  e.ports[0].postMessage(URL.createObjectURL(e.data));
  close();
};
© www.soinside.com 2019 - 2024. All rights reserved.