首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在ManifestV3服务工作者中将一个大块下载到本地文件

在ManifestV3服务工作者中将一个大块下载到本地文件
EN

Stack Overflow用户
提问于 2022-08-13 23:08:59
回答 1查看 407关注 0票数 1

我有一个日志机制,可以将日志保存到一个数组中。我需要一种将日志下载到文件中的方法。

我以前使用过这个(清单v2)

代码语言:javascript
运行
复制
const url = URL.createObjectURL(new Blob(reallyLongString, { type: 'text/plain' }));
const filename = 'logs.txt';
chrome.downloads.download({url, filename});

现在我要迁移到清单v3,而且由于清单v3没有URL.createObjectURL,所以不能创建传递给chrome.downloads.download的url。

相反,可以使用以下内容创建Blob

代码语言:javascript
运行
复制
const url = `data:text/plain,${reallyLongString}`; 
const filename = 'logs.txt';
chrome.downloads.download({url, filename});

问题似乎限制了在url参数中传递的字符数,并且下载的文件只包含字符串的一小部分。

那么,怎样才能克服这一限制呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-14 08:43:58

希望能够在https://crbug.com/1224027中实现一种直接在服务工作者中下载Blob的方法。

通过扩展页面解决问题

下面是算法:

  1. 使用已打开的页面,如弹出或选项
  2. 否则,将iframe注入到我们可以访问的任何页面中。
  3. 否则,打开一个新的最小化窗口。
代码语言:javascript
运行
复制
async function downloadBlob(blob, name, destroyBlob = true) {
  // When `destroyBlob` parameter is true, the blob is transferred instantly,
  // but it's unusable in SW afterwards, which is fine as we made it only to download
  const send = async (dst, close) => {
    dst.postMessage({blob, name, close}, destroyBlob ? [await blob.arrayBuffer()] : []);
  };
  // try an existing page/frame
  const [client] = await self.clients.matchAll({type: 'window'});
  if (client) return send(client);
  const WAR = chrome.runtime.getManifest().web_accessible_resources;
  const tab = WAR?.some(r => r.resources?.includes('downloader.html'))
    && (await chrome.tabs.query({url: '*://*/*'})).find(t => t.url);
  if (tab) {
    chrome.scripting.executeScript({
      target: {tabId: tab.id},
      func: () => {
        const iframe = document.createElement('iframe');
        iframe.src = chrome.runtime.getURL('downloader.html');
        iframe.style.cssText = 'display:none!important';
        document.body.appendChild(iframe);
      }
    });
  } else {
    chrome.windows.create({url: 'downloader.html', state: 'minimized'});
  }
  self.addEventListener('message', function onMsg(e) {
    if (e.data === 'sendBlob') {
      self.removeEventListener('message', onMsg);
      send(e.source, !tab);
    }
  });
}

downloader.html:

代码语言:javascript
运行
复制
<script src=downloader.js></script>

downloader.js、popup.js、options.js和其他扩展页面脚本(不是内容脚本):

代码语言:javascript
运行
复制
navigator.serviceWorker.ready.then(swr => swr.active.postMessage('sendBlob'));
navigator.serviceWorker.onmessage = async e => {
  if (e.data.blob) {
    await chrome.downloads.download({
      url: URL.createObjectURL(e.data.blob),
      filename: e.data.name,
    });
  }
  if (e.data.close) {
    window.close();
  }
}

manifest.json:

代码语言:javascript
运行
复制
"web_accessible_resources": [{
  "matches": ["<all_urls>"],
  "resources": ["downloader.html"],
  "use_dynamic_url": true
}]

警告!,因为"use_dynamic_url": true尚未执行,如果你不想让你的扩展被网页发现的话,不要添加web_accessible_resources。

通过屏幕外文档解决问题

很快就会有另一个解决办法: chrome.offscreen.createDocument而不是chrome.windows.create来启动一个不可见的DOM页面,在这里我们可以调用URL.createObjectURL,将结果传回给将用于chrome.downloads.download的SW。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73348151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档