我有一个日志机制,可以将日志保存到一个数组中。我需要一种将日志下载到文件中的方法。
我以前使用过这个(清单v2)
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
const url = `data:text/plain,${reallyLongString}`;
const filename = 'logs.txt';
chrome.downloads.download({url, filename});
问题似乎限制了在url参数中传递的字符数,并且下载的文件只包含字符串的一小部分。
那么,怎样才能克服这一限制呢?
发布于 2022-08-14 08:43:58
希望能够在https://crbug.com/1224027中实现一种直接在服务工作者中下载Blob的方法。
通过扩展页面解决问题
下面是算法:
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:
<script src=downloader.js></script>
downloader.js、popup.js、options.js和其他扩展页面脚本(不是内容脚本):
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:
"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。
https://stackoverflow.com/questions/73348151
复制相似问题